Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.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 如何在Linux上同步终止进程?_C_Linux_Process - Fatal编程技术网

C 如何在Linux上同步终止进程?

C 如何在Linux上同步终止进程?,c,linux,process,C,Linux,Process,当我对进程调用kill()时,它会立即返回,因为它只发送一个信号。我有一个代码,我在其中无限地检查循环中的一些进程(外来的、我没有编写或修改的),如果它们超过了某些限制(内存消耗过多等),它就会杀死它们(并写入系统日志等) 问题是,当进程被大量交换时,杀死它们需要很多秒,因此,我的进程多次对相同的进程执行相同的检查,并多次尝试将信号发送到相同的进程,并将其写入syslog。(这不是故意的,这只是我正在努力解决的一个副作用) 我不关心它向进程发送信号多少次,但我关心它向syslog写入多少次。我可

当我对进程调用kill()时,它会立即返回,因为它只发送一个信号。我有一个代码,我在其中无限地检查循环中的一些进程(外来的、我没有编写或修改的),如果它们超过了某些限制(内存消耗过多等),它就会杀死它们(并写入系统日志等)

问题是,当进程被大量交换时,杀死它们需要很多秒,因此,我的进程多次对相同的进程执行相同的检查,并多次尝试将信号发送到相同的进程,并将其写入syslog。(这不是故意的,这只是我正在努力解决的一个副作用)

我不关心它向进程发送信号多少次,但我关心它向syslog写入多少次。我可以保留一个已发送终止信号的PID列表,但从理论上讲,即使概率很低,也可能会有另一个进程生成另一个与先前终止的进程相同的PID,该进程也可能被终止,在这种情况下,日志将丢失


我不知道是否有任何进程的唯一标识符,但我对此表示怀疑。如何同步终止进程,或者跟踪收到信号且不需要再次记录的进程?

这将使脚本等待进程终止

kill $PID
while [ kill -0 $PID 2>/dev/null  ]
do
     sleep 1
done

kill-0[pid]
测试进程的存在性

如果用C编写,则发送带有
kill
系统调用的信号。不要重复发送终止信号,只需发送一次,然后使用
kill(pid,0)循环(或以某种方式定期检查)信号的零值只会告诉您进程是否仍处于活动状态,并且您可以采取适当的行动。当它死亡时,
kill
将返回
ESRCH

  • 生成这些进程时,可以使用经典的
    waitpid(2)
    系列

  • 当不在其他地方使用时,您可以将要终止的进程移动到自己的cgroup中;这些cgroup上可能有通知程序,当进程退出时会触发这些通知程序

  • 要查明进程是否已被终止,您可以
    chdir(2)
    进入
    /proc/
    打开(2)
    此目录。进程终止后,无法再访问其中的状态文件。此方法是快速的(在检查和操作之间,进程可以终止,并生成具有相同pid的新进程)

即使您可以执行“同步终止”,您仍然有可能终止错误进程的竞争条件。只要您想杀死的进程自愿退出,或者在您看到它之后,在您杀死它之前,通过第三方操作退出,就可以发生这种情况。在此间隔期间,可将PID分配给新流程。这个问题基本上没有解决办法。PID本质上是一种本地资源,属于已识别流程的父级;任何其他进程使用PID都是竞争条件

如果您对系统有更多的控制(例如,控制要终止的进程的父进程),那么可能会有特殊情况的解决方案。也可能有(特定于Linux的)解决方案基于使用
/proc
中的一些机制来避免竞争,尽管我不知道有任何解决方案

另一种解决方法是在目标进程上使用
ptrace
,就好像您要调试它一样。这允许您部分“窃取”父角色,避免在仍在使用PID时使其无效,并允许您在进程终止时获得通知。你可以这样做:

  • 检查流程信息(例如来自
    /proc
    )以确定是否要终止它
  • ptrace
    it,暂时停止它
  • 重新检查进程信息以确保您得到了想要终止的进程
  • 继续跟踪过程
  • 杀死它
  • 等待(通过
    waitpid
    )进程退出的通知

  • 以下解决方案适用于大多数不是调试器的进程或正在调试器中调试的进程

    • 使用带有参数的
      ptrace\u ATTACH
      附加到流程。这将停止您想要终止的进程。此时,您可能应该验证是否已连接到正确的流程
    • 使用
      SIGKILL
      杀死目标。它现在不见了
    • 我不记得这个过程现在是否是一个你需要收获的僵尸,或者你是否需要先
      PTRACE\u CONT
      it。在任何一种情况下,您最终都必须调用
      waitpid
      来获取它,此时您知道它已经死了

    可能在要终止的进程中有一个信号处理程序,它在接收到SIGINT时写入文件,然后终止self?但这个进程正在监视外部进程,不仅是我编写的进程,而且可以修改。您测试了吗?我认为你不希望杀戮命令被[和]左右。我很确定你只是做了
    而kill-0$PID 2>/dev/null
    当进程可以杀死不止一个PID时是否会阻塞?如果另一个进程是用旧PID生成的,这可能会挂起。谢谢你的回答,这不关我说的是c,这段代码也很好,只是它不能100%工作-如果在两次kill调用之间有另一个进程产生了相同的pid,它会继续检查,但不是同一个进程如果该进程存在并且它不响应SIGTERM(第一次kill),那么这将运行到一个无限循环中。如果在两次kill调用之间(pid,0),会发生什么;进程死亡,而另一个进程使用相同的pid生成?这是极不相似的,但也是可能的。在这种情况下,esrch不会被返回。你现在是如何通过信号轰炸过程来避免这种情况的?我现在不是在避免它,我想知道如何避免它