2012-03-29 32 views
0

Ich verwende das Producer/Consumer-Problem, um einen Multi-Thread-DNS-Resolver zu erstellen. Ich habe es ohne Multithreading gelöst, also bin ich mir ziemlich sicher, dass dieser Teil meines Codes funktioniert. Im Grunde erstelle ich einen Produzenten zum Schreiben und (wird viele erstellen) zum Lesen. Zur Zeit lese ich aus einer Datei mit IP-Adressen darin ein. Ich kann nicht herausfinden, warum mein Producer-Thread nicht läuft. Ich muss herausfinden, was los ist, bevor ich meine Kunden zum Laufen bringen kann. Jede Hilfe wird sehr geschätzt.Producer/Consumer-Threads arbeiten nicht mit Pthread für DNS-Lookup

hier ist mein Code (bisher):

/* 
* dns_lookup.c 
*/ 


#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <pthread.h> 
#include <semaphore.h> 
#include "linkedlist.h" 

const int BUFF_SIZE = 20; 

int ip_count; 

FILE *fp; 

list_t *list; 

pthread_mutex_t mutex; 


void *do_work(char *addr) 
{ 
struct addrinfo hints; 
struct addrinfo *result; 
char hbuf[NI_MAXHOST]; 


int rc = 0; 
int count = 0; 

// initialize the addrinfo struct 
memset(&hints, 0, sizeof(hints)); 
hints.ai_family = AF_UNSPEC; 
hints.ai_socktype = SOCK_DGRAM; 
hints.ai_flags = AI_PASSIVE; 
hints.ai_protocol = 0; 
hints.ai_canonname = NULL; 
hints.ai_addr = NULL; 
hints.ai_next = NULL; 

// convert the dotted-quad address to an ip address 
rc = getaddrinfo(addr, NULL,&hints, &result); 
if (rc != 0) { 
    fprintf(stderr,"getaddrinfo failed: %s\n", gai_strerror(rc)); 
    exit(EXIT_FAILURE); 
} 

printf("%s -> ", addr); 

rc = getnameinfo(result->ai_addr, result->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD); 
if (count++ > 0) printf(","); 
if (rc != 0) { 
    printf("%s", addr); 
} 
else { 
    printf("%s",hbuf); 
} 

result = result->ai_next; 

printf("\n"); 
} 

void *producer(void *param); 
void *consumer(void *param); 
void *init(); 

int main(int argc, char **argv[]) 
{ 
fp=fopen("access.log", "r"); 

list = malloc(sizeof(list_t)); 
list->head = NULL; 

pthread_t producer_tid; 
pthread_t consumer_tid; 

pthread_attr_t attr; 

pthread_mutex_init(&mutex, NULL); 
pthread_attr_init(&attr); 

pthread_create(&producer_tid, &attr, producer, NULL); 
} 




void *producer(void *param) 
{ 
printf("%s", "thread created"); 
char line[1024]; 

while (!feof(fp)) 
{ 
    fgets(line, sizeof line, fp); 
    char *tempstr = strtok(line, " "); 
    char *ipaddr = malloc(sizeof(char) * 50); 
    strncpy(ipaddr, tempstr, 20); 
    pthread_mutex_lock(&mutex); 
    add(list, ipaddr); 
    node_t *temp = get(list, 0); 
    printf("%s\n", temp->data); 
    pthread_mutex_unlock(&mutex); 
} 
} 

void *consumer(void *param) 
{ 
char *addr; 
addr = get(list, 0); 
do_work(addr); 
} 

EDIT: ich einige meiner Code festgelegt, und ich denke, dass es funktionieren sollte. Es tut es aber immer noch nicht.

/* 
* dns_lookup.c 
*/ 


#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <pthread.h> 
#include <semaphore.h> 
#include "linkedlist.h" 

const int BUFF_SIZE = 20; 

int ip_count; 

FILE *fp; 

list_t *list; 

sem_t full; 
sem_t empty; 

pthread_mutex_t mutex; 


void *do_work(char *addr) 
{ 
    struct addrinfo hints; 
    struct addrinfo *result; 
    char hbuf[NI_MAXHOST]; 


    int rc = 0; 
    int count = 0; 

    // initialize the addrinfo struct 
    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_DGRAM; 
    hints.ai_flags = AI_PASSIVE; 
    hints.ai_protocol = 0; 
    hints.ai_canonname = NULL; 
    hints.ai_addr = NULL; 
    hints.ai_next = NULL; 

    // convert the dotted-quad address to an ip address 
    rc = getaddrinfo(addr, NULL,&hints, &result); 
    if (rc != 0) { 
     fprintf(stderr,"getaddrinfo failed: %s\n", gai_strerror(rc)); 
     exit(EXIT_FAILURE); 
    } 

    printf("%s -> ", addr); 

    rc = getnameinfo(result->ai_addr, result->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD); 
    if (count++ > 0) printf(","); 
    if (rc != 0) { 
     printf("%s", addr); 
    } 
    else { 
     printf("%s",hbuf); 
    } 

    result = result->ai_next; 

    printf("\n"); 

    //exit(EXIT_SUCCESS); 
} 

void *producer(void *param); 
void *consumer(void *param); 
void *init(); 

void main(int argc, char **argv[]) 
{ 
    fp=fopen("access.log", "r"); 

    list = malloc(sizeof(list_t)); 
    list->head = NULL; 

    int thread_count = atoi(argc); 


    pthread_t producer_tid; 
    pthread_t consumer_tid[thread_count]; 

    pthread_attr_t attr; 

    //ip_count = 0; 

    sem_init(&full, 0, 0); 
    sem_init(&empty, 0, BUFF_SIZE); 

    pthread_mutex_init(&mutex, NULL); 
    pthread_attr_init(&attr); 


    pthread_create(&producer_tid, NULL, producer, NULL); 

    int threads; 
    for(threads=0; threads<=thread_count; threads++) 
    { 
     pthread_create(&consumer_tid[threads], NULL, consumer, NULL); 
    } 

    pthread_join(producer_tid, NULL); 

    for(threads=0; threads<=thread_count; threads++) 
    { 
     pthread_join(consumer_tid[threads], NULL); 
    } 

    exit(fp); 
    exit(EXIT_SUCCESS); 
} 

void *producer(void *param) 
{ 
    printf("thread created%s"); 
    char line[1024]; 
    while (1) 
    { 
     sem_wait(&empty); 
     while (!feof(fp)) 
     { 
      fgets(line, sizeof line, fp); 
      char *tempstr = strtok(line, " "); 
      char *ipaddr = malloc(sizeof(char) * 50); 
      strncpy(ipaddr, tempstr, 20); 
      pthread_mutex_lock(&mutex); 
      add(list, ipaddr); 
      node_t *temp = get(list, 0); 
      printf("%s\n", temp->data); 
      pthread_mutex_unlock(&mutex); 
     } 
     sem_post(&full); 
    } 
} 

void *consumer(void *param) 
{ 
    while(1) 
    { 
     sem_wait(&full); 
     pthread_mutex_lock(&mutex); 
     char *addr; 
     addr = get(list, 0); 
     do_work(addr); 
     remove_head(list); 
     pthread_mutex_unlock(&mutex); 
     sem_post(&empty); 
    } 

} 

Ich sehe nichts arbeiten. Irgendwelche Vorschläge?

Ich erhalte Segfaults, wenn ich es debugge. Ich weiß nicht warum oder woher sie kommen. Ich bin neu bei PThreads, also habe ich vielleicht etwas verpasst, aber für mich sieht es so aus, als ob es funktionieren sollte.

+0

Wenn Sie es in einem Debugger debuggen, sollte der Debugger auf der Zeile anhalten, wo der Fehler ist. Vielleicht können Sie diese Zeile auf uns verweisen , oder fügen Sie zumindest einen Stack-Trace (gdb-Befehl 'bt') zu Ihrer Frage hinzu.Im Debugger können Sie Variablen untersuchen, um zu sehen, ob sie gut aussehen und es keinen 'NULL'-Punkt gibt zum Beispiel. –

Antwort

0

Ich nehme an, dass Ihr Produzent-Thread tatsächlich läuft ... für eine sehr kurze Zeit. In Ihrer main() Funktion legen Sie den Producer-Thread und dann unmittelbar danach das Programm beendet (weil die main Funktion zurück Versuchen Sie, diese hinzufügen, bevor Sie zurückkommen.

pthread_join(producer_tid, &return_value_p); 

Sobald Sie Verbraucher-Threads starten erstellen, müssen Sie sicherstellen, Sie warten auch darauf, dass alle beendet sind, bevor Sie Ihr Programm beenden.

+0

Ich verstehe nicht, woher & return_value_p kommt. Ich habe versucht, 'Pthread_join (Produzent_TID, NULL) zu verwenden;' aber es tat nichts. Der & return_value_p ist nicht deklariert, daher erhalte ich einen Fehler. – user1181577

+0

Nun, natürlich müssen Sie es erklären. Aber gemäß der Manpage ist es optional, so dass "NULL" in Ordnung ist. Auch nach der Manpage habe ich die Art des ersten Arguments nicht richtig verstanden. Wird bearbeiten. – Celada

+0

"Sie müssen sicherstellen, dass Sie auch darauf warten, dass alle fertig sind, bevor Sie Ihr Programm beenden." Warum? –