检查进程是否存在,给定它的pid。

54

给定 Linux 进程的 pid,我想要在 C 程序中检查该进程是否仍在运行。


你可能想看看这个:https://dev59.com/gnNA5IYBdhLWcg3wfd8m - xtrem
6个回答

107

以信号0调用kill(2)系统调用。如果调用成功,则意味着存在此pid的进程。

如果调用失败并且errno设置为ESRCH,则不存在具有该pid的进程。

引用POSIX标准:

如果sig为0(空信号),则执行错误检查但实际上不发送任何信号。空信号可用于检查pid的有效性。

请注意,您不能安全地避免竞争条件: 目标进程可能已经退出,并且与此同时启动了具有相同pid的另一个进程。或者进程可能在您检查它之后非常快地退出,您可能会根据过时的信息做出决定。

只有给定pid是子进程(从当前进程中fork出来的进程)的情况下,您可以使用带有WNOHANG选项的waitpid(2),或者尝试捕获SIGCHLD信号。 这些对于子进程是安全的,但只与子进程相关。


7
调用成功并不意味着进程存在。它意味着某个具有该PID的进程存在,这个进程可能是他想了解的进程,也可能不是。 - David Schwartz
18
只有在测试的进程是您自己的子进程时,kill 方法才是安全的。在这种情况下,进程 ID 属于您自己,直到您 wait 为止,它才能被重用。否则,任何使用 pid 都是严重的错误。 - R.. GitHub STOP HELPING ICE
在按照您的示例并查看kill()函数的手册页后,我得到了返回值-1,而不是预期的ESRCH。我做错了什么吗?perror()显示“没有这个进程”。 - Marvin Effing
1
@MarvinEffing 我知道这是一个旧回复,但如果它能帮助其他人,你必须检查 errno。如果出现错误,kill() 的返回代码将为-1。这在答案中和文档中也有指出。 - SRG

19

kill(pid, 0) 是典型的方法,如@blagovest-buyukliev所说。但是如果您要检查的进程可能属于不同的用户,而且您不想采取额外的步骤来检查 errno == ESRCH,那么结果表明:

(getpgid(pid) >= 0)

如果你想确定是否有任何进程具有给定的PID(即使你可以检查不属于你的进程的进程组ID),那么这是一种有效的一步方法。


有时进程退出但getpgid(pid)仍返回正值。 - tianyapiaozi
2
@tianyapiaozi 我怀疑如果是这种情况,进程已经"退出"但还没有被"收割"(进程记录仍然存在于"僵尸"状态,直到父进程检查它以获取其返回值)。你说得对,虽然这里如果一个进程"存在"是没有严格定义的。我非常有信心,至少如果这个表达式返回true,那么kill(pid, 0)也会返回true。 - the paul
1
必要的头文件是 <unistd.h> - ph_0

18
使用procfs。
#include <sys/stat.h>
[...]
struct stat sts;
if (stat("/proc/<pid>", &sts) == -1 && errno == ENOENT) {
  // process doesn't exist
}

轻松适用于

  • Solaris
  • IRIX
  • Tru64 UNIX
  • BSD
  • Linux
  • IBM AIX
  • QNX
  • 来自贝尔实验室的Plan 9

4
你可以使用信号值为0来调用kill(2)系统调用。 kill -0对程序没有任何不安全的影响。程序必须意识到结果随时可能会过时(包括在调用kill之前pid可能会被重新使用),这就是全部内容。而且,使用procfs也确实使用了pid,而且以一种更加繁琐和非标准的方式进行。

3
作为/proc文件系统方法的补充,您可以检查/proc//cmdline(假设它是从命令行启动的)以查看它是否是您想要的进程。

2
命令行有两个含义 - 其中一个(在/proc/<pid>/cmdline中)是“运行的程序名称,带有传递给它的参数列表”,适用于每个进程,即使不是从“命令行”启动(不同的含义:为了人类受益而设计的基于文本的界面)。 - AMADANON Inc.

-3
ps -p $PID > /dev/null 2>&1;   echo $?

如果进程使用$PID仍在运行,则此命令返回0。否则,它将返回1

在OSX终端中也可以使用此命令。


1
那并没有回答问题(“*...来自C程序*”),并且遭受与kill方法相同的竞态条件的困扰。 - melpomene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接