使用pthreads互斥锁的C中的同步问题

时间:2011-04-01 15:11:25

标签: c synchronization pthreads mutex

我正在使用一个简单的队列实现,我正在尝试创建一个包含两个线程的简单程序:队列中的第一个队列事件和第二个队列事件处理它们。我正在使用互斥锁来避免同步问题。但是,我仍然经常(并非总是)出现分段错误。

请注意,我也使用-D_REENTRANT选项构建了代码。此外,如果仅从一个线程调用queue / dequeue,则代码可以正常工作。

这是一个简单的代码,显示了我如何同步这些东西:

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;
                }
            }
        }
    }
}

我希望我没有用如此多的代码压倒你,但这真的很简单。

所以我的问题是关于同步我做错了什么?

谢谢!

更新

这是队列实现:

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;
}

它在*value = q->first->data;中的dequeue行上进行了段错误。

谢谢!

2 个答案:

答案 0 :(得分:2)

一个小问题是:

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

(注意添加的星号)。

主要问题似乎是你没有在process_events函数中为*being_fetched分配内存。

说实话,我会将该变量的类型更改为struct input_event *being_fetched,并将其地址简单地传递给dequeuehas_item = dequeue(&my_queue, &being_fetched)。这也可以让你摆脱ev作为一个单独的变量。

答案 1 :(得分:1)

正如aix所说,你没有初始化* being_fetched。但我认为你最好不同地定义它:

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

然后绝对确定你修复了aix提到的另一个错误,否则你不会将空指针退回到函数之外。