/ proc / <pid>何时删除?

时间:2019-02-22 08:11:33

标签: linux linux-kernel

进程A在运行时打开&&映射了数千个文件。然后发出killl -9 <pid of process A>。然后我对以下两个事件的顺序有疑问。
a)无法访问/proc/<pid of process A>
b)关闭由进程A打开的所有文件。

有关此问题的更多背景:
进程A是一个多线程后台服务。它由cmd ./process_A args1 arg2 arg3启动。
还有一个看门狗进程,用于检查进程A是否仍定期(每1秒)处于活动状态。如果进程A已死,则重新启动它。看门狗检查进程A的方式如下。
1)收集/proc/下的所有数值子目录
2)将/proc/<all-pids>/cmdline与进程A的cmdline进行比较。如果它们与/proc/<some-pid>/cmdline匹配,则进程A仍然存在并且不执行任何操作,否则重新启动进程A。

进程A在进行初始化时将执行以下操作。
1)打开文件A
2)群文件A
3)mmap fileA进入内存
4)关闭文件A
初始化后,进程A将映射成千上万个文件。 几分钟后,将发出kill -9 <pid of process A>。 看门狗检测到进程A的死亡,然后重新启动它。但是有时进程A停留在step 2 flock fileA处。经过一些调试后,我们发现杀死进程A时将执行文件A的解锁。但是有时此事件会在step 2 flock fileA新流程之后发生。
因此,我们猜想监视器/proc/<pid of process A>是否可以动态检查进程 不正确。

2 个答案:

答案 0 :(得分:3)

  

然后发布kill -9

这是坏习惯。您最好先发送SIGTERM。因为行为良好的流程和设计良好的程序可以捕获它(并在获得SIGTERM时退出正确)。在某些情况下,我甚至建议:发送SIGTERM。等待两三秒钟。发送SIGQUIT。等待两秒钟。最后,发送一个SIGKILL信号(用于那些未正确编写或行为异常的不良程序)。几秒钟后,您可以发送SIGKILL。阅读signal(7)signal-safety(7)。在多线程但特定于Linux的程序中,您可以使用signalfd(2)pipe(7)进行自欺骗(在Qt文档中为explained,但不是Qt特定)。

如果您的Linux系统是基于systemd的,则可以想象您的 program-A 是使用 systemd 工具启动的。然后,您将使用systemd工具与之“通信”。在某些方面(我不知道细节),systemd使得signals几乎过时了。请注意,信号不是多线程友好的,并且在上个世纪已经针对单线程进程进行了设计。

  

我们猜测通过监视器/ proc /检查运行状态的方法不正确。

检测进程是否存在(您具有足够的特权,例如,与uid / gid一起运行)的通常的方法(并且足够快,并且是“原子的”)是将kill(2)与信号号(kill的第二个参数)为0。引用该联机帮助页:

   If sig is 0, then no signal is sent, but existence and permission
   checks are still performed; this can be used to check for the
   existence of a process ID or process group ID that the caller is
   permitted to signal.

当然,该其他进程仍然可以在与它进行任何进一步的交互之前终止。因为Linux具有抢先式调度功能。

您的看门狗进程最好使用kill( pid-of-process-A , 0)检查该 process-A 的存在和活跃性。使用/proc/ pid-of-process-A /并不是正确的方法。

无论您编写什么代码,该 process-A 都可能异步消失(特别是,如果它存在导致分段错误的错误)。当进程终止时(即使出现分段错误),内核对其文件锁起作用(并“释放”它们)。

答案 1 :(得分:2)

不要扫描/proc/PID来确定特定进程是否已终止。有很多更好的方法可以做到这一点,例如让您的看门狗程序实际启动服务器程序并等待其终止。

或者,让看门狗在TCP套接字上侦听,并使服务器进程连接到该套接字并发送其PID。如果任一端死亡,则另一端可以注意到连接已关闭(提示:每隔一段时间向心动的对等方发送心跳数据包)。如果看门狗在另一个服务器仍在运行时从另一个服务器接收到连接,则它可以决定允许它或告诉其中一个实例关闭(通过TCP或kill())。