为何MacOS终端execlp调用ps时,ps不在自身列表显示?Linux却正常
问题:fork子进程执行ps -l在MacOS中无法找到自身PID的原因
我修改了一个基于fork()的C语言模板,让子进程执行ps -l命令,原本期望在ps输出列表中找到该子进程(验证其PID与执行ps前的子进程PID一致)。该代码在Ubuntu系统上运行完全正常,但在MacOS系统中,无法在输出里找到ps进程的条目。请问造成这种差异的原因是什么?
对应的C语言代码
#include <stdio.h> /* Pour perror */ #include <stdlib.h> /* Pour exit */ #include <unistd.h> /* Pour fork, getpid, getppid, sleep */ #include <sys/types.h> /* Pour pid_t (fork, getpid, getppid) */ #include <sys/wait.h> /* Pour wait */ int main(void) { pid_t ident; ident = fork(); if (ident == -1) { perror("fork"); return EXIT_FAILURE; } /* A partir de cette ligne, il y deux processus */ printf("Cette ligne sera affichee deux fois\n"); if (ident == 0) { /* Code execute uniquement par le fils */ printf("Je suis le fils, PID: %d, père: %d\n", getpid(), getppid()); execlp("ps", "ps", "-l", NULL); } else { /* Code execute uniquement par le pere */ printf("Je suis le pere\n, PID: %d, père: %d\n", getpid(), getppid()); wait(NULL); } return EXIT_SUCCESS; }
原因分析
核心差异来自Linux与macOS平台ps工具的实现逻辑不同:
Ubuntu(Linux)的
ps行为:当子进程通过execlp启动ps -l后,ps会遍历系统进程列表,此时自身进程已经完成初始化并被纳入系统进程表,因此输出中会包含该ps进程的条目(PID与原叉子进程一致,因为exec系列调用不会改变进程PID)。MacOS的
ps行为:macOS上的ps工具在生成进程快照时,会主动排除自身进程的记录。也就是说,ps在收集并输出进程信息时,不会把正在运行的自己加入到结果列表里,所以你看不到对应的PID条目。
验证方法
可以在子进程的execlp调用前加入sleep(1),然后再执行ps -l:
// 子进程代码中添加sleep printf("Je suis le fils, PID: %d, père: %d\n", getpid(), getppid()); sleep(1); // 新增延迟 execlp("ps", "ps", "-l", NULL);
此时用top或活动监视器实时查看,能看到该ps进程存在,但ps -l的输出里依然找不到它,这就证明是ps工具的输出规则导致的,而非进程未创建。
另外注意代码中父进程的printf存在格式错误:"Je suis le pere\n, PID: ..."里的\n不应该放在逗号前,会导致输出换行混乱,但这与当前问题无关。
内容的提问来源于stack exchange,提问作者Nocta
相关产品推荐
相关产品推荐

