gpt4 book ai didi

c - 在多进程设置中等待等待条件的线程未被唤醒

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:06:04 25 4
gpt4 key购买 nike

我在使用 Linux 上 pthreads 的等待条件和互斥锁来进行进程间同步时遇到了一个奇怪的问题。请注意,这不仅仅是一个进程中的线程之间。

我的用例是有一个生产者创建资源(在我的例子中是图像),将它们保存到共享内存区域,更新有关资源的一些信息,然后向等待的消费者发出信号。共享内存和元数据部分工作正常,所以我将其排除在外,问题是信号无法可靠地工作。用例很简单,因为消费者错过一两张图像并不重要,如果消费者还没有时间阅读,生产者基本上只是覆盖一张旧图像。所以等待条件只需要处理唤醒消费者,我不需要任何资源计数或其他数据。

生产者和消费者都有这样的结构:

struct EventData {
pthread_mutex_t mutexHandle;
pthread_cond_t conditionHandle;
};

消费者进程中的线程等待某事发生:

pthread_mutex_lock( &eventData->mutexHandle );
pthread_cond_wait( &eventData->conditionHandle, &eventData->mutexHandle );
thread_mutex_unlock( &eventData->mutexHandle );

生产进程在创建图像、将其保存到共享内存并准备好让消费者抓取图像时执行此操作:

pthread_mutex_lock( &eventData->mutexHandle );
pthread_cond_signal( &eventData->conditionHandle );

// also tried:
//pthread_cond_broadcast( &eventData->conditionHandle );
pthread_mutex_unlock( &eventData->mutexHandle );

这对我来说看起来很不错,并且在某种程度上有效。生产者可以毫无问题地向消费者发出大约 100-1000 次信号,消费者醒来,抓取图像并展示它,结果是我可以看到移动的视频。在某个时刻,通常在几百帧左右,消费者将卡住在 pthread_cond_wait() 中并且永远不会返回。生产者仍然愉快地创建图像,调用 pthread_cond_signal() 并继续没有问题。消费者并没有完全卡住,只有执行 pthread_cond_wait() 的线程,应用程序的其余部分运行没有问题。

因此,当信号从一个线程移动到另一个进程中的另一个线程时,某些原因会导致信号丢失。消费者卡住前通常需要 5-20 秒,唤醒工作的次数也在 100 到 1000 之间变化(基于目前看到的值)。

由于默认情况下在进程之间共享互斥锁和等待条件并非微不足道,我使用此设置来创建原语:

    EventData * eventData;

int fd = open( tmpnam(NULL), O_RDWR | O_CREAT | O_EXCL, 0666);
if (fd < 0) {
// failed to open file for event
}

if ( ftruncate(fd, sizeof (eventData )) < 0 ) {
// failed to truncate file
}

// setup attributes to allow sharing between processes
pthread_condattr_init( &conditionAttribute );
pthread_condattr_setpshared( &conditionAttribute, PTHREAD_PROCESS_SHARED );
pthread_mutexattr_init( &mutexAttribute );
pthread_mutexattr_setpshared( &mutexAttribute, PTHREAD_PROCESS_SHARED );

// map memory for the event struct
eventData = (EventData *) mmap(NULL, sizeof(EventData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close (fd);

// finally initialize the memory
pthread_mutex_init( &eventData->mutexHandle, &mutexAttribute );
pthread_cond_init( &eventData->conditionHandle, &conditionAttribute );

以上是由创建互斥锁和等待条件的一方完成的。文件的名称,即 tmpnam(NULL) 实际上已保存并传递给其他进程以打开:

    int fd = open( nameOfEventFile, O_RDWR, 0666 );
if (fd < 0) {
// failed to open file for event
}

eventData = (EventData *) mmap( NULL, sizeof(EventData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
close( fd );

我在这里没有看到任何错误,并且希望得到一些关于可能出错的提示,尤其是当它在随机时间工作时。

最佳答案

当我写完 95% 的问题时,这个错误就戳到了我的眼睛……我仍然决定把它和修正一起放在这里,以防其他人偶然发现类似的东西。创建互斥锁和等待条件的部分如下所示:

EventData * eventData;

int fd = open( tmpnam(NULL), O_RDWR | O_CREAT | O_EXCL, 0666);
if (fd < 0) {
// failed to open file for event
}

if ( ftruncate(fd, sizeof (eventData )) < 0 ) {
// failed to truncate file
}

如果仔细观察,您会发现 ftruncate() 截断为 eventData 指针的大小,而不是 struct EventData 的大小。因此,这里需要的一个字符修复是:

if ( ftruncate(fd, sizeof (EventData )) < 0 ) {
// failed to truncate file
}

确实是个愚蠢的错误。

关于c - 在多进程设置中等待等待条件的线程未被唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13377677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com