Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 信号安全使用sem_wait()/sem_post()_C_Posix - Fatal编程技术网

C 信号安全使用sem_wait()/sem_post()

C 信号安全使用sem_wait()/sem_post(),c,posix,C,Posix,我正在尝试在Linux上创建一个包装器,它控制一次允许多少并发执行。为此,我使用了一个系统范围的计数信号量。我创建信号量,执行sem\u wait(),启动子进程,然后在子进程终止时执行sem\u post()。那很好 问题是如何安全地处理发送到此包装器的信号。如果它没有捕获信号,则该命令可能会在不执行sem\u post()的情况下终止,从而导致信号量计数永久减少1。因此,我创建了一个信号处理程序,它执行sem\u post()。但仍然存在一个问题 如果在执行sem\u wait()之前附加处

我正在尝试在Linux上创建一个包装器,它控制一次允许多少并发执行。为此,我使用了一个系统范围的计数信号量。我创建信号量,执行
sem\u wait()
,启动子进程,然后在子进程终止时执行
sem\u post()
。那很好

问题是如何安全地处理发送到此包装器的信号。如果它没有捕获信号,则该命令可能会在不执行
sem\u post()
的情况下终止,从而导致信号量计数永久减少1。因此,我创建了一个信号处理程序,它执行
sem\u post()
。但仍然存在一个问题

如果在执行
sem\u wait()
之前附加处理程序,则信号可能在
sem\u wait()
完成之前到达,导致在没有
sem\u wait()
的情况下发生
sem\u post()
。如果在设置信号处理程序之前执行
sem\u wait()
,则可能出现相反的情况

显然,下一步是在设置处理程序和
sem\u wait()
期间阻止信号。这是我现在拥有的伪代码:

void handler(int sig)
{
  sem_post(sem);
  exit(1);
}

...
sigprocmask(...);   /* Block signals */
sigaction(...);     /* Set signal handler */
sem_wait(sem);
sigprocmask(...);   /* Unblock signals */
RunChild();
sem_post(sem);
exit(0);
现在的问题是,
sem\u wait()
会阻塞,在此期间,信号会被阻塞。试图终止进程的用户最终可能会求助于“kill-9”,这是我不想鼓励的行为,因为我无论如何都无法处理这种情况。我可以使用
sem\u trywait()
一小段时间,然后测试
sigpunding()
,但这会影响公平性,因为不再保证等待信号量最长的进程将在下一个运行


这里是否有一个真正安全的解决方案,允许我在信号量采集期间处理信号?我正在考虑使用“我是否拥有信号量”全局设置并移除信号阻塞,但这不是100%安全的,因为获取信号量并设置全局设置不是原子的,但可能比在等待时阻塞信号要好。

你确定
sem_wait()
会导致信号阻塞吗?我认为情况并非如此。表示如果被信号中断,则从
sem_wait()
返回
EINTR
错误代码

您应该能够处理此错误代码,然后您的信号将被接收。您是否遇到过未接收到信号的情况


我会确保您处理
sem\u wait()
可以返回的错误代码。虽然这可能很少见,但如果你想100%确定你想要覆盖100%的基础。

你确定你正确处理了这个问题吗?如果要等待子进程终止,可能需要使用
waitpid()
系统调用。正如您所观察到的,如果孩子可能接收到信号,那么期望孩子做
sem\u post()
是不可靠的。

我知道这很古老,但对于那些仍然阅读谷歌提供的这篇文章的人来说


对于这个问题,最简单(也是唯一?)的健壮解决方案是使用System V信号量,它允许客户端以内核自动返回的方式获取信号量资源,无论进程如何退出。

如果我不清楚,很抱歉。sem_wait()不会像您所说的那样导致信号被阻塞,但我正在使用sigprocmask()来阻止它们。但是,我认为您有一个正确的解决方案,那就是查看EINTR错误代码,这意味着处理程序不应该退出,而应该设置一些标志来表示“退出时间”。我来测试一下。谢谢,这很有效。我移除了对信号的阻塞,并将信号处理程序更改为只设置一个全局值,这意味着是时候退出了。如果sem_wait()返回错误,那么我退出,这很好,并保留信号量计数。如果我在等孩子,我也会测试退出global的时间。如果是时候退出了,我会杀死这个孩子并执行一个sem_post()来保存信号量计数。谢谢这应该是信号安全的,忽略kill-9。实际上,子级不知道信号量,父级在伪代码中的RunChild()函数中执行waitpid(),我没有显示。这一部分很好,它正在处理孩子的终止以及在sem_take()完成后发送给家长的信号。我担心设置信号处理程序和sem_wait()之间的关键部分,但检查sem_wait()错误代码是我看不到的简单解决方案。