Sté*_*ane 47 linux gcc semaphore g++
我有多个使用g ++编译的应用程序,在Ubuntu中运行.我正在使用命名信号量来协调不同的进程.
一切正常,除非在以下情况下:如果其中一个进程调用sem_wait()或sem_timedwait()减少信号量然后在它有机会调用之前崩溃或被杀死-9 sem_post(),那么从那一刻起,命名信号量就"无法使用".
通过"不可用",我的意思是信号量计数现在为零,并且应该将其增加回1的过程已经死亡或被杀死.
我找不到一个sem_*()API,可能会告诉我上次减少崩溃的过程.
我在某个地方错过了API吗?
以下是我打开命名信号量的方法:
sem_t *sem = sem_open( "/testing",
O_CREAT | // create the semaphore if it does not already exist
O_CLOEXEC , // close on execute
S_IRWXU | // permissions: user
S_IRWXG | // permissions: group
S_IRWXO , // permissions: other
1 ); // initial value of the semaphore
Run Code Online (Sandbox Code Playgroud)
这是我如何减少它:
struct timespec timeout = { 0, 0 };
clock_gettime( CLOCK_REALTIME, &timeout );
timeout.tv_sec += 5;
if ( sem_timedwait( sem, &timeout ) )
{
throw "timeout while waiting for semaphore";
}
Run Code Online (Sandbox Code Playgroud)
Sté*_*ane 41
事实证明,没有办法可靠地恢复信号量.当然,任何人都可以post_sem()通过指定的信号量让计数再次增加到零,但是如何判断何时需要这样的恢复?提供的API太有限,并且在发生这种情况时不以任何方式表明.
的IPC工具也可当心-常用工具ipcmk,ipcrm以及ipcs只对过时的SysV信号灯.它们特别适用于新的POSIX信号量.
但看起来还有其他东西可用于锁定事物,当应用程序以无法在信号处理程序中捕获的方式死亡时,操作系统会自动释放.两个示例:绑定到特定端口的侦听套接字或特定文件上的锁.
我决定锁定文件是我需要的解决方案.所以我没有使用sem_wait()和sem_post()调用,而是使用:
lockf( fd, F_LOCK, 0 )
Run Code Online (Sandbox Code Playgroud)
和
lockf( fd, F_ULOCK, 0 )
Run Code Online (Sandbox Code Playgroud)
当应用程序以任何方式退出时,文件将自动关闭,这也会释放文件锁定.等待"信号量"的其他客户端应用程序可以按预期自由进行.
谢谢你的帮助,伙计们.
使用锁定文件而不是信号量,就像@Stéphane的解决方案,但没有flock()调用.您只需使用独占锁即可打开文件:
//call to open() will block until it can obtain an exclusive lock on the file.
errno = 0;
int fd = open("/tmp/.lockfile",
O_CREAT | //create the file if it's not present.
O_WRONLY | //only need write access for the internal locking semantics.
O_EXLOCK, //use an exclusive lock when opening the file.
S_IRUSR | S_IWUSR); //permissions on the file, 600 here.
if (fd == -1) {
perror("open() failed");
exit(EXIT_FAILURE);
}
printf("Entered critical section.\n);
//Do "critical" stuff here.
//exit the critical section
errno = 0;
if (close(fd) == -1) {
perror("close() failed");
exit(EXIT_FAILURE);
}
printf("Exited critical section.\n");
Run Code Online (Sandbox Code Playgroud)
这是管理信号量时的典型问题。一些程序使用单个过程来管理信号量的初始化/删除。通常,此过程仅执行此操作,而不执行其他操作。您的其他应用程序可以等到信号灯可用为止。我已经看到这是通过SYSV类型的API完成的,但不是通过POSIX完成的。与提到的“ Duck ” 类似,在semop()调用中使用SEM_UNDO标志。
但是,根据您提供的信息,我建议您不要使用信号量。特别是如果您的过程有被杀死或崩溃的危险。尝试使用操作系统将为您自动清理的内容。