xYZ*_*xYZ 1 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。
还有一个看门狗进程,它定期(每 1 秒)检查进程 A 是否还活着。如果进程 A 死亡,则重新启动它。看门狗检查进程A的方式如下。
1)收集2)
下的所有数字子目录与进程A的cmdline进行比较。如果这些匹配,则进程A处于活动状态并且不执行任何操作,否则重新启动进程A。/proc//proc/<all-pids>/cmdline/proc/<some-pid>/cmdline
进程A在初始化时会做以下事情。
1)打开fileA
2)flock fileA
3)mmap fileA到内存中
4)关闭fileA
进程A在初始化后将mmap上千个文件。几分钟后,kill -9 <pid of process A>发出。看门狗检测到进程A死亡,重新启动它。但有时进程 A 卡在step 2 flock fileA。经过一番调试,我们发现当进程A被杀死时,就会执行fileA的unlock。但有时此事件会在step 2 flock fileA新流程之后发生。
所以我们猜测通过监视器检查进程是否存活的方式/proc/<pid of process A>
是不正确的。
然后
kill -9发出
这是坏习惯。你最好SIGTERM先发一份。因为行为良好的进程和设计良好的程序可以捕获它(并在获得...时很好地正确SIGTERM退出)。在某些情况下,我什至建议:发送SIGTERM. 等待两三秒钟。发送SIGQUIT. 等两秒钟。最后,发送一个SIGKILL信号(对于那些没有正确编写或行为不当的不良程序)。几秒钟后,您可以发送一个SIGKILL. 读取signal(7)和signal-safety(7)。在多线程但特定于Linux的程序中,您可以使用signalfd(2)或pipe(7)来进行自我欺骗(Qt文档中有很好的解释,但不是Qt特定的)。
如果您的 Linux 系统是基于systemd的,您可以想象您的程序 A是使用systemd设施启动的。然后您将使用 systemd 设施与其“通信”。在某些方面(我不知道细节),systemd 正在使信号几乎过时。请注意,信号对多线程并不友好,并且在上个世纪是为单线程进程设计的。
我们猜测通过监视器 /proc/ 检查进程是否存活的方法不正确。
检测进程是否存在(您有足够的权限,例如使用您的 uid/gid 运行)的通常(更快,并且足够“原子”)的方法是使用带有信号号( ) 的第二个参数为kill0。引用该联机帮助页:
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.
Run Code Online (Sandbox Code Playgroud)
当然,该其他进程仍然可以在与其进行任何进一步交互之前终止。因为Linux有抢占式调度。
您的看门狗进程应该更好地使用kill(pid-of-process-A, 0)来检查该process-A的存在性和活跃性。使用/proc/pid-of-process-A/ 并不是正确的方法。
无论您编写什么代码,该进程 A 都可能会异步消失(特别是,如果它有一些导致分段错误的错误)。当进程终止时(即使存在分段错误),内核也会对其文件锁进行操作(并“释放”它们)。