网站建设 服务内容 费用,qq小程序权限设置,app定制开发哪个公司好,wordpress网站推翻重建简介#xff1a;
在这篇博客中#xff0c;我们将深入探索如何在 C 程序中实现子进程的创建与执行#xff0c;以及父子进程间的管道通信。核心代码提供了一个框架#xff0c;用于接收用户命令、创建子进程并利用 execvp 系统调用执行这些命令。此外#xff0c;我们通过创建…简介
在这篇博客中我们将深入探索如何在 C 程序中实现子进程的创建与执行以及父子进程间的管道通信。核心代码提供了一个框架用于接收用户命令、创建子进程并利用 execvp 系统调用执行这些命令。此外我们通过创建管道pipe展示了如何在父子进程间安全地传递数据。
本文重点介绍 fork, pipe, 和 execvp 的使用方法并解释了如何将标准输出和标准错误从子进程重定向到父进程。这一过程涉及对 Unix 系统调用的深入理解尤其是进程间通信IPC的概念。我们的目标是提供一个清晰的指南帮助读者理解和实现在现代操作系统中广泛应用的进程创建、执行和通信机制。
该教程适合对操作系统、进程管理以及 Unix/Linux 系统编程感兴趣的读者。无论是系统编程新手还是有经验的开发者都可以通过这个实例加深对进程间通信和命令行界面CLI应用编程的理解。
exec相关
一共有六个分三组记忆
execlp - execvp
execl - execv
execle - execve这几个函数的速记
记忆口诀如下
0、exec是通用前缀 1、 p 代表第一个参数是file 也就是程序的名字比如 ls 如果名字没带p, 代表第一个参数是path, 比如 /bin/ls 2、 l 代表参数传递的是list, 参数是一个个传递的最后一个参数为NULL 3、 v 代表argv 参数是用char* 数组传递的 4、 e 代表环境变量
1、execlp l-list,p- file 参数就是(file, a1, a2, a3,..., NULL);
2、execvp v-argv,p-file. 参数就是file, aegv
3、execl l-list,没p - path 参数就是(path, a1, a2, a3, ..., NULL);
4、execv v-argv,没p-path 参数(path, argv);
5、execle l-list,没p-path, e-env 参数(path, a0, a1, ..., NULL, env);
6、execve v-aegv,没p-path, e-env 参数(path, argv, env);实战代码
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h
#include string.h
#include iostream
#include stringbool isCommandSupport(std::string command) {if (command ls || command pwd || command ps || command cat || command grep ||command wc || command exit) {return true;}return false;
}void childTask() {while (true) {// 获得一整行输入std::string line;size_t len 0;std::getline(std::cin, line);// 进行分割char *p strtok((char *) line.c_str(), );char *argv[100];int argc 0;while (p ! NULL) {argv[argc] p;p strtok(NULL, );}argv[argc] NULL;if (argc 0) {continue;}if (isCommandSupport(argv[0])) {if (strcmp(argv[0], exit) 0) {exit(0);}} else {printf(command not support\n);continue;}int pipefd[2];pid_t pid;char buf;if (pipe(pipefd) -1) {perror(pipe);exit(EXIT_FAILURE);}pid fork();if (pid -1) {perror(fork);exit(EXIT_FAILURE);}if (pid 0) { /* 子进程 */close(pipefd[0]); // 关闭读端dup2(pipefd[1], STDOUT_FILENO); // 将标准输出重定向到管道写端dup2(pipefd[1], STDERR_FILENO); // 将标准错误也重定向到管道写端close(pipefd[1]); // 关闭原始写端execvp(argv[0], argv);_exit(EXIT_FAILURE);} else { /* 父进程 */close(pipefd[1]); // 关闭写端while (read(pipefd[0], buf, 1) 0) {write(STDOUT_FILENO, buf, 1);}close(pipefd[0]); // 关闭读端int status;waitpid(pid, status, 0);if (WIFEXITED(status)) {} else if (WIFSIGNALED(status)) {printf(child terminated abnormally, signal %d\n, WTERMSIG(status));}}}
}int main() {childTask();
}