07-检查进程的存在
20.6 检查进程的存在
kill()系统调用还有另一重功用。若将参数sig指定为0(即所谓空信号),则无信号发送。相反,kill()仅会去执行错误检查,查看是否可以向目标进程发送信号。从另一角度来看,这意味着,可以使用空信号来检测具有特定进程ID的进程是否存在。若发送空信号失败,且errno为ESRCH,则表明目标进程不存在。如果调用失败,且errno为EPERM(表示进程存在,但无权向目标进程发送信号)或者调用成功(有权向进程发送信号),那么就表示进程存在。
验证一个特定进程ID的存在并不能保证特定程序仍在运行。因为内核会随着进程的生灭而循环使用进程ID。而一段时间之后,同一进程ID所指恐怕是另一进程了。此外,特定进程ID可能存在,但是一个僵尸(亦即,进程已死,但其父进程尚未执行wait()来获取其终止状态,如26.2节所述)。
还可使用各种其他技术来检查某一特定进程是否正在运行,其中包括如下技术。
- wait()系统调用:第26章将描述这些调用。这些调用仅用于监控调用者的子进程。
- 信号量和排他文件锁:如果进程持续持有某一信号量或文件锁,并且一直处于被监控状态,那么如能获取到信号量或锁时,即表明该进程已经终止。第47章和第53章将描述信号量,第55章将描述文件锁。
- 诸如管道和FIFO之类的IPC通道:可对监控目标进程进行设置,令其在自身生命周期内持有对通道进行写操作的打开文件描述符。同时,令监控进程持有针对通道进行读操作的打开文件描述符,且当通道写入端关闭时(遭遇文件结束符),即可获知监控目标进程已经终止。监控进程对此情况的判定,既可借助于对自身文件描述符的读取,也可采用第63章所述的描述符监控技术之一。
- /proc/PID接口:例如,如果进程ID为12345的进程存在,那么目录/proc/12345将存在,可以发起诸如stat()之类的调用来进行检查。
除去最后一项之外,循环使用进程ID不会影响上述所有技术。
程序清单20-3展示了kill()的用法。该程序接受两个命令行参数,分别为信号编号和进程ID,并使用kill()将该信号发送给指定进程。如果指定了信号0(空信号),那么程序将报告目标进程是否存在。