2011-04-01 72 views
0

我正在使用一個簡單的隊列實現,我試圖做一個簡單的程序,它有兩個線程:隊列中的第一個隊列事件和第二個隊列處理它們。我正在使用互斥鎖來避免同步問題。但是,我仍然經常(並非總是)出現分段錯誤。C使用pthreads互斥鎖同步問題

請注意,我也使用-D_REENTRANT選項建立了我的代碼。另外,如果僅從一個線程調用隊列/出隊,則代碼工作得很好。

下面是簡單的代碼,顯示我是如何同步的東西:

int main(void) { 
    init_queue(&my_queue); 

    pthread_t thread_queue, thread_process; 
    int iret1, iret2; 

    iret1 = pthread_create(&thread_queue, NULL, svetlin_queue_events, (void*) NULL); 
    iret2 = pthread_create(&thread_process, NULL, svetling_process_events, (void*) fb); 

    pthread_join(thread_queue, NULL); 
    pthread_join(thread_process, NULL); 
} 

的排隊功能:

void svetlin_queue_events(void * v) { 
    int fd; 
    if ((fd = open("/dev/input/mouse1", O_RDONLY)) == -1) { 
     printf("error with touchscreen device\n"); 
     exit(1); 
    } 

    struct input_event ev; 
    struct input_event *being_sent; 
    int rd; 

    while (1) { 
     read(fd, &ev, sizeof(struct input_event)); 

     being_sent = malloc(sizeof(struct input_event)); 
     memcpy(being_sent, &ev, sizeof(struct input_event)); 

     pthread_mutex_lock(&my_mutex); 
     enqueue(&my_queue, being_sent); 
     pthread_mutex_unlock(&my_mutex); 

     printf("enqueueing...\n"); 
    } 
} 

和處理功能:

void svetling_process_events(void *v) { 

    printf("FB pointer is: %p\n", fb); 

    int x, y = 0; 
    int has_item = 0; 
    struct input_event **being_fetched; 
    struct input_event *ev; 

    while(1) { 

     pthread_mutex_lock(&my_mutex); 
     has_item = dequeue(&my_queue, being_fetched); 
     pthread_mutex_unlock(&my_mutex); 

     if (has_item) { 
      ev = *being_fetched; 
      printf("dequeueing...\n"); 
      if (ev->type == 3) { 
       if (ev->code == 0) { 
        x = ev->value; 
       } 

       if (ev->code == 1) { 
        y = ev->value; 
       } 
      } 
     } 
    } 
} 

我希望我用這麼多代碼不會讓你感到困惑,但它確實很簡單。

所以我的問題是關於同步我做錯了什麼?

謝謝!

UPDATE

這裏的隊列實現:

struct queue_node 
{ 
    struct queue_node *next; 
    void *data; 
}; 

struct queue 
{ 
    struct queue_node *first; 
    struct queue_node *last; 
}; 

int enqueue(struct queue *q, void * const value) 
{ 
    struct queue_node *node = malloc(sizeof(struct queue_node)); 

    if (node == NULL) { 
     errno = ENOMEM; 
     return 1; 
    } 

    node->data = value; 

    if (q->first == NULL) { 
     q->first = q->last = node; 
    } else { 
     q->last->next = node; 
     q->last = node; 
    } 

    node->next = NULL; 
    return 0; 
} 

int dequeue(struct queue *q, void **value) 
{ 
    if (!q->first) { 
     value = NULL; 
     return 0; 
    } 
    *value = q->first->data; 
    q->first = q->first->next; 
    return 1; 
} 

void init_queue(struct queue *q) 
{ 
    q->first = q->last = NULL; 
} 

int queue_empty_p(const struct queue *q) 
{ 
    return q->first == NULL; 
} 

它出現segfaults在dequeue*value = q->first->data;

謝謝!

+0

哪裏在代碼中它segfault? – NPE 2011-04-01 15:12:52

+0

我知道有一個內存泄漏,因爲我沒有刪除創建的東西,但我不認爲這是問題。 – 2011-04-01 15:13:03

+0

在我的排隊功能。我會發布它,如果你認爲它可以幫助 – 2011-04-01 15:13:37

回答

2

一個次要的問題是:

if (!q->first) { 
    *value = NULL; 
    return 0; 
} 

(注意加星號)。

主要問題似乎是您在process_events函數中沒有爲*being_fetched分配內存。

說實話,我會將該變量的類型改爲,並簡單地將其地址傳遞給dequeuehas_item = dequeue(&my_queue, &being_fetched)。這也可以讓你擺脫ev作爲一個單獨的變量。

+0

是的,沒錯。還有一個事實是,我應該釋放一些mem在我的出隊功能中。這並不重要,因爲它也不能解釋段錯誤。 – 2011-04-01 15:26:21

+0

我很困惑。我什麼都沒做,只是重新編譯並運行它並沒有給出任何問題...... – 2011-04-01 15:28:30

+1

它(第二點)幾乎肯定會。您正在寫入由未初始化的指針指向的內存。 – NPE 2011-04-01 15:29:27

1

正如aix所說,你沒有init * being_fetched。但我認爲你最好還是不同定義它:

struct input_event *being_fetched; 
... 
has_item = dequeue(&my_queue, &being_fetched); 
... 
ev = being_fetched; 

然後讓絕對確保你修復AIX提到了其他錯誤,否則你不會得到空指針背出功能。

+1

黨,甚至艾克斯的退出比我的快。 +1。 :-) – BMitch 2011-04-01 15:29:15

+0

是的。儘管如此,非常感謝麻煩:-)真的很友善。 – 2011-04-01 15:42:05