【问题标题】:Condition variables working on MacOS but not Ubuntu适用于 MacOS 但不适用于 Ubuntu 的条件变量
【发布时间】:2020-01-09 03:46:18
【问题描述】:

我有一些 C 代码在 MacOS 上完美运行。 很快,我就有了一个进程,它需要一个互斥体,在管道上写入,解锁互斥体并向条件变量发送信号。 然后,有另一个进程会监听这个管道,并在收到信号时读取缓冲区并将内容写入本地文件。

问题是完全相同的代码在 Linux Ubuntu 上不起作用。

我尝试更改互斥锁和条件变量的实现,遵循互联网上的提示,但没有奏效。

这里有一些代码可以更好地解释:

首先,我将互斥锁和条件初始化为进程共享

    pthread_mutexattr_t mutexAttr = {};
    pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(&mutex, &mutexAttr);

    pthread_condattr_t condAttr = {};
    pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
    pthread_cond_init(&condition, &condAttr);

这是在读取管道并写入文件的进程上运行的函数

    char buffer[8192];
    while(1) {
        bzero(buffer, sizeof buffer);
        pthread_cond_wait(&condition, &mutex);
        pthread_mutex_lock(&mutex);
        read(pipe_fd[0], buffer, sizeof buffer);
        _log(buffer);
        pthread_mutex_unlock(&mutex);
    }

最后这是在另一个进程上运行并写入管道的代码

    char *buffer = malloc(SIZE);
    sprintf(buffer, "name: %s | size: %d | ip: %s | server_port: %d\n", name, size, client_ip, port);
    pthread_mutex_lock(&mutex);
    if (write(pipe_fd[1], buffer, strlen(buffer)) < 0) {
        pthread_mutex_unlock(&mutex);
        free(buffer);
        return -1;
    }
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&condition);

似乎在 Ubuntu 上,当我调用 pthread_cond_signal(&condition) 时它不会返回错误,但也不会触发条件变量,因此调用 pthread_cond_wait(&condition, &mutex) 的进程永远不会通过。

奇怪的是,互斥体工作得很好,管道也是。

【问题讨论】:

  • 真实代码是否也缺少所有错误检查? pthread_*() 函数返回有用的信息。错误检查(和日志记录)正在免费调试。

标签: c macos ubuntu pthreads condition-variable


【解决方案1】:

条件变量使用错误。

应该是:

在消费者线程中:

pthread_mutex_lock(&mutex);
pthread_cond_wait(&condition, &mutex); //Automatically unlocks the mutex and waits for signal.
pthread_mutex_unlock(&mutex);

在生产者线程中:

pthread_mutex_lock(&mutex);
pthread_cond_signal(&condition);
pthread_mutex_unlock(&mutex);

由于您在评论中提到它仍然无法正常工作,请尝试以下代码。

   char buffer[8192];
    while(1) {
        bzero(buffer, sizeof buffer);
        pthread_mutex_lock(&mutex);
        while(!flag) {    //Share the flag between the process and initialize to zero. This is required to handle spurious signals.
            pthread_cond_wait(&condition, &mutex); //Automatically mutex will be unlocked. It will be locked again when signal is detected.
        }
        flag = 0; //Reset flag
        pthread_mutex_unlock(&mutex);
        read(pipe_fd[0], buffer, sizeof buffer);
        _log(buffer);
    }

char *buffer = malloc(SIZE);
sprintf(buffer, "name: %s | size: %d | ip: %s | server_port: %d\n", name, size, client_ip, port);
//pthread_mutex_lock(&mutex); //No need to lock here
if (write(pipe_fd[1], buffer, strlen(buffer)) < 0) {
    //pthread_mutex_unlock(&mutex);
    free(buffer);
    return -1;
}
pthread_mutex_lock(&mutex);
flag=1; //Update the flag.
pthread_cond_signal(&condition);
pthread_mutex_unlock(&mutex);

【讨论】:

  • 好吧,我不知道它会自动解锁互斥锁。顺便说一句,我尝试了这个解决方案,但什么也没发生
  • 可能是因为杂散信号。请查看此帖子:stackoverflow.com/a/13122435/6284997
  • 谢谢,这部分解决了我的问题。它现在可以工作,但是在第一次请求之后,它会停止处理信号。稍后我会进一步调查,再次感谢您。
猜你喜欢
  • 2020-06-26
  • 2019-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
相关资源
最近更新 更多