当我在进程上调用kill()时,它会立即返回,因为它只是发送一个信号。我有一个代码,我在一个循环中无限地检查一些(外来的,不是写的也不可修改的)进程,如果它们超过一些限制(太多ram吃掉等)它会杀死它们(并写入syslog等)。 / p>
问题是,当进程被大量交换时,它需要很多秒才能终止它们,因此,我的进程多次对同一进程执行相同的检查,并尝试多次向同一进程发送信号,并写入这也是syslog。 (这不是故意的,只是我试图解决的副作用)
我不关心它发送信号的次数,但我关心它写入syslog的次数。我可以保留已经发送了杀死信号的PID列表,但理论上,即使可能性很低,也可能会有另一个过程产生与之前已杀死的相同的pid ,这可能是也应该被杀死,在这种情况下,日志将丢失。
我不知道是否有任何进程的唯一标识符,但我对此表示怀疑。我怎么能同步杀死一个进程,或者跟踪那些得到信号并且不需要再次记录的进程?
答案 0 :(得分:6)
即使你可以进行“同步杀戮”,你仍然有竞争条件可以杀死错误的进程。只要您想要杀死的进程在您看到它之后但在您杀死之前通过自己的意志或第三方操作退出,就会发生这种情况。在此间隔期间,可以将PID分配给新进程。这个问题基本上没有解决方案。 PID本质上是属于所识别进程的父级的本地资源;任何其他过程使用PID都是竞争条件。
如果您对系统有更多控制权(例如,控制要杀死的进程的父进程),则可能存在特殊情况解决方案。可能还有(特定于Linux的)解决方案基于使用/proc
中的某些机制来避免竞争,尽管我不知道任何。
另一种解决方法可能是在目标进程上使用ptrace
,就像您要调试它一样。这允许您部分“窃取”父角色,避免在您仍在使用PID时使PID失效,并允许您在进程终止时收到通知。你会做类似的事情:
/proc
)以确定您要将其删除。ptrace
它,暂时停止它。kill
它。waitpid
)获取流程退出的通知。答案 1 :(得分:1)
这将使脚本等待进程终止。
kill $PID
while [ kill -0 $PID 2>/dev/null ]
do
sleep 1
done
kill -0 [pid]
测试进程的存在
答案 2 :(得分:1)
以下解决方案适用于非调试器中调试的调试器或进程的大多数进程。
ptrace
的{{1}}附加到流程。这会停止您要杀死的进程。此时,您应该验证您是否已附加到正确的流程。PTRACE_ATTACH
杀死目标。它现在已经消失了。SIGKILL
它。在任何一种情况下,你最终都必须致电PTRACE_CONT
来收获它,此时你知道它已经死了。答案 3 :(得分:0)
如果您在C中写这个,那么您正在发送带有kill
系统调用的信号。而不是重复发送终止信号只需发送一次,然后循环(或以某种方式定期检查)kill(pid, 0);
信号的零值将告诉您进程是否仍然存在并且您可以采取适当的行动。当它死亡时kill
将返回ESRCH
。
答案 4 :(得分:0)
当您产生这些过程时,可以使用经典的waitpid(2)
系列
如果不在其他任何地方使用,您可以将要杀死的进程移动到自己的cgroup中;这些cgroup上可以有通知,当进程退出时会触发。
要查明进程是否已被终止,您可以chdir(2)
进入/proc/<pid>
或open(2)
此目录。进程终止后,无法再访问那里的状态文件。这种方法很有效(在您的检查和操作之间,流程可以终止,并且生成具有相同pid的新流程)。