一个用户崩溃时共享内存互斥?

假设一个进程正在共享内存中创build一个互斥锁,并在互斥锁被locking时locking它并转储核心。

现在在另一个过程中,我如何检测互斥锁已经被locking,但不属于任何进程?

如果你在Linux或类似的工作,考虑使用命名的信号,而不是(我认为是)pthreads互斥。 我不认为有一种方法可以确定一个pthreads互斥量的锁定PID,而不是建立自己的注册表并将其放在共享内存中。

似乎确切的答案是以强大的互斥体的形式提供的。

根据POSIX,可以使用pthread_mutexattr_setrobust()将pthread互斥锁初始化为“健壮”。 如果持有该互斥锁的进程死亡,下一个获得它的线程将收到EOWNERDEAD(但仍然成功获取互斥锁),以便知道执行任何清理。 然后需要使用pthread_mutex_consistent()通知获取的互斥量再次一致。

显然你需要内核和libc支持这个工作。 在Linux上,内核支持被称为“健壮的futexes”,我发现引用了glibc HEAD应用的用户空间更新。

在实践中,至少在Linux世界中似乎还没有被滤除。 如果这些函数不可用,那么您可能会发现pthread_mutexattr_setrobust_np(),就我所能收集而言,它似乎是提供相同语义的非POSIX前驱。 我在Solaris文档和Debian上的/usr/include/pthread.h中都找到了对pthread_mutexattr_setrobust_np()的引用。

POSIX规范可以在这里找到: http : //www.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html

如何基于文件的锁定(使用flock(2) )? 当持有它的进程死亡时,它们会自动释放。

演示程序:

 #include <stdio.h> #include <time.h> #include <sys/file.h> void main() { FILE * f = fopen("testfile", "w+"); printf("pid=%u time=%u Getting lock\n", getpid(), time(NULL)); flock(fileno(f), LOCK_EX); printf("pid=%u time=%u Got lock\n", getpid(), time(NULL)); sleep(5); printf("pid=%u time=%u Crashing\n", getpid(), time(NULL)); *(int *)NULL = 1; } 

输出(为了清晰起见,我已经截断了PID和时间):

 $ ./a.out & sleep 2 ; ./a.out [1] 15 pid=15 time=137 Getting lock pid=15 time=137 Got lock pid=17 time=139 Getting lock pid=15 time=142 Crashing pid=17 time=142 Got lock pid=17 time=147 Crashing [1]+ Segmentation fault ./a.out Segmentation fault 

发生什么事是第一个程序获得了锁并开始休眠5秒钟。 2秒后,程序的第二个实例开始在尝试获取锁的同时阻塞。 3秒钟后,第一个程序segfaults(bash直到后来才告诉你),第二个程序获得锁定并继续。

您应该使用操作系统提供的信号量。

操作系统释放一个进程已经打开的所有资源,无论是死亡还是正常退出。

我离开这个错误的职位,只有当有人会有相同的想法,并会发现这个讨论的使用!


你可以使用这种方法。 1)锁定POSIX共享互斥锁2)将进程ID保存在共享内存中。 3)解锁共享互斥锁4)在正确的出口清理进程ID

如果进程崩溃,下一个进程会发现在共享内存中有一个在步骤#2中保存的进程ID。 如果在OS中没有这个进程ID的进程,那么没有人拥有共享的互斥量。 所以只需要替换进程ID。

更新以回答评论:

场景1:1.P1开始2.P1创建/打开一个已命名的互斥体(如果不存在)3.P1定时锁定已命名的互斥体,并成功地完成(如果需要,等待10秒)。 4. P1 coredumps 5. P2在coredump后启动6. P2创建/打开一个已命名的互斥锁,它存在,它是OK 7. P2 timed_locks已命名的互斥锁并失败锁定(如果需要,等待10秒); 8. P2删除指定的互斥锁9. P2重新创建一个已命名的互斥锁并将其锁定