- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在使用 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/
我是一名优秀的程序员,十分优秀!