Linux环境下C程序创建子进程执行ls/ps命令的实现咨询
实现两个子进程分别执行ls和ps的C代码方案
嘿,作为Linux和C编程的新手,你的需求完全没问题——就是用C代码创建两个子进程,分别让它们跑ls和ps命令对吧?我先给你捋清楚核心逻辑的伪代码,再给你可直接运行的完整代码,最后提几个新手容易踩的坑,帮你少走弯路。
核心逻辑伪代码
先给你写个伪代码,帮你理解整体流程:
// 主程序入口 int main() { // 创建第一个子进程(用来执行ls) pid_t 子进程1ID = fork(); if (子进程1ID == 0) { // 这里是子进程1的执行逻辑 调用exec系列函数,把当前进程替换成ls命令 如果exec调用失败,打印错误信息 退出子进程 } else if (子进程1ID > 0) { // 主进程继续创建第二个子进程(用来执行ps) pid_t 子进程2ID = fork(); if (子进程2ID == 0) { // 这里是子进程2的执行逻辑 调用exec系列函数,把当前进程替换成ps命令 如果exec调用失败,打印错误信息 退出子进程 } else if (子进程2ID > 0) { // 主进程等待两个子进程都执行完毕 等待子进程1结束 等待子进程2结束 } else { // 创建第二个子进程失败的处理 打印fork失败的错误信息 } } else { // 创建第一个子进程失败的处理 打印fork失败的错误信息 } return 0; }
可运行的完整C代码
上面的伪代码转成实际可编译运行的C代码如下,我加了详细的注释:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { // 创建第一个子进程,用于执行ls命令 pid_t pid_ls = fork(); if (pid_ls == 0) { // execlp会自动从系统PATH环境变量中查找ls程序 // 参数格式:execlp(程序名, 传给程序的argv[0], 可选参数, NULL) execlp("ls", "ls", "-l", NULL); // 注意:如果execlp执行成功,下面的代码永远不会被执行 // 只有exec失败时才会走到这里,打印错误并退出 perror("execlp failed to run ls"); exit(EXIT_FAILURE); } else if (pid_ls < 0) { // fork创建子进程失败 perror("failed to fork ls process"); exit(EXIT_FAILURE); } // 创建第二个子进程,用于执行ps命令 pid_t pid_ps = fork(); if (pid_ps == 0) { // execvp和execlp的区别是参数用数组传递 char *ps_arguments[] = {"ps", "aux", NULL}; execvp("ps", ps_arguments); // 同样,exec成功的话不会走到这里 perror("execvp failed to run ps"); exit(EXIT_FAILURE); } else if (pid_ps < 0) { perror("failed to fork ps process"); exit(EXIT_FAILURE); } // 主进程等待两个子进程都执行完成,避免产生僵尸进程 waitpid(pid_ls, NULL, 0); waitpid(pid_ps, NULL, 0); printf("两个子进程都已执行完毕\n"); return 0; }
编译运行的话,直接用gcc:
gcc process_demo.c -o process_demo ./process_demo
新手必看的注意事项
- 务必处理fork的所有返回情况:fork会返回三个值——0(子进程)、正整数(父进程拿到的子进程PID)、负数(创建失败),三个分支都要处理,不然容易出现隐藏bug。
- exec系列函数成功不会返回:一旦exec调用成功,当前进程的代码段、数据段会被新程序完全替换,所以exec后面的代码只有在调用失败时才会执行,一定要加错误处理和exit。
- 必须等待子进程:如果主进程不调用
waitpid或wait,子进程结束后会变成“僵尸进程”,占用系统的进程表资源,直到主进程退出才会被清理。 - 命令参数要以NULL结尾:不管用execlp还是execvp,参数列表的最后必须是NULL,不然程序会读取到内存中的垃圾数据,导致执行异常。
- 可以自定义命令参数:比如我给ls加了
-l参数,给ps加了aux参数,你可以根据需求改成自己想要的参数,甚至去掉参数直接用"ls", NULL。
内容的提问来源于stack exchange,提问作者MrRoger2
相关产品推荐
相关产品推荐

