Warm tip: This article is reproduced from serverfault.com, please click

linux-在C程序中查找由exec()或system()启动的进程的PID

(linux - Finding the PID of a process launched by exec() or system() in C program)

发布于 2021-02-10 18:20:44

我需要检索由 exec() 或 system() 启动的进程的 PID。我阅读了该主题并进行了研究,但我不明白使用 fork() 这样做的建议。

假设我有以下代码:

int pid = fork();

if (pid < 0 ) {
exit(1);
} else if (pid == 0 ) {
execlp("ls", "-a", NULL);
} else {
wait(0)
}

如何获取由 execlp 启动的进程的 pid(如果使用 system,则由 system() 启动)?我不需要终止进程,我只需要 PID 来检索有关它的统计信息。

Questioner
JavaDumbell
Viewed
0
Oka 2021-02-11 05:41:01

exec*函数族不会创建新进程,而是将调用它们的进程的执行上下文替换为其目标可执行文件的执行上下文。发生这种情况时,PID 将保持不变。

#include <unistd.h>
#include <stdio.h>

int main(void) {
    /* Normal execution */
    puts("Hello");

    /* Our programs contents get "replaced" by ls */
    execlp("ls", "-l", NULL);

    /* We never get here */
    puts("World!");
}

fork,另一方面,创建一个新的子进程,它当然有自己的 PID。这个子进程继续执行它产生的相同执行上下文的副本;你可以将执行视为“拆分”,一旦fork被调用。在子进程中fork返回0,在父进程(我们的原始进程)中返回子进程的PID。

思路是fork,然后用exec*来替换子进程的执行上下文。

#include <unistd.h>
#include <stdio.h>

int main(void) {
    pid_t pid;
    /* Normal execution */
    puts("Hello");

    /* execution "splits" */
    pid = fork();
    if (pid == 0) {
        /* Our child's execution context get "replaced" by ls */
        execlp("ls", "-l", NULL);
    } else {
        /* still in the parent */
        printf("Child PID is: %d\n", (int) pid);
    }

    /* We only get here in the parent */
    puts("World!");
}

system是围绕 的包装器forkexec*并且waitpid会阻止调用进程,直到子进程完成其执行。孩子的PID没有上报,因为到父母可以再次“行动”的时候,孩子的PID已经没有意义了。


错误处理省略的例子清晰,但你应该处理的错误forkexec*wait*功能。