如何用C编写通过管道、fork、exec控制B、C进程完成计算的程序A
C语言程序A实现方案
实现逻辑说明
- 总共需要创建4个管道:分别对应B的输入(A写、B读)、B的输出(B写、A读)、C的输入(A写、C读)、C的输出(C写、A读)
- 两次调用
fork()创建子进程,子进程内通过dup2()将标准输入、标准输出重定向到对应管道,之后调用exec()启动已开发完成的B、C程序 - 父进程关闭不需要的管道端,生成初始随机数后按要求循环100次迭代,每次数据传输后间隔1秒,同时按指定格式打印进程间通信日志
完整代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <time.h> #include <string.h> int main() { // 管道定义:fd[0]读端,fd[1]写端 int b_in[2], b_out[2]; // B的输入、输出管道 int c_in[2], c_out[2]; // C的输入、输出管道 // 创建所有管道 if (pipe(b_in) < 0 || pipe(b_out) < 0 || pipe(c_in) < 0 || pipe(c_out) < 0) { perror("创建管道失败"); exit(1); } // 启动子进程B pid_t pid_b = fork(); if (pid_b < 0) { perror("fork B失败"); exit(1); } else if (pid_b == 0) { // 子进程B:重定向标准输入到b_in读端,标准输出到b_out写端 close(b_in[1]); close(b_out[0]); dup2(b_in[0], STDIN_FILENO); dup2(b_out[1], STDOUT_FILENO); // 关闭无关管道 close(c_in[0]); close(c_in[1]); close(c_out[0]); close(c_out[1]); // 执行B程序,假设B的可执行文件名为./b execlp("./b", "./b", NULL); perror("exec B失败"); exit(1); } // 启动子进程C pid_t pid_c = fork(); if (pid_c < 0) { perror("fork C失败"); exit(1); } else if (pid_c == 0) { // 子进程C:重定向标准输入到c_in读端,标准输出到c_out写端 close(c_in[1]); close(c_out[0]); dup2(c_in[0], STDIN_FILENO); dup2(c_out[1], STDOUT_FILENO); // 关闭无关管道 close(b_in[0]); close(b_in[1]); close(b_out[0]); close(b_out[1]); // 执行C程序,假设C的可执行文件名为./c execlp("./c", "./c", NULL); perror("exec C失败"); exit(1); } // 父进程A:关闭不需要的管道端 close(b_in[0]); close(b_out[1]); close(c_in[0]); close(c_out[1]); // 初始化随机数 srand(time(NULL)); int current = rand() % 100; // 初始随机数取0-99之间,可按需调整范围 // 循环迭代100次 for (int i = 1; i <= 100; i++) { char buf[64] = {0}; // 1. 给B发数据 printf("%03d. A -> B %d\n", i, current); sprintf(buf, "%d\n", current); write(b_in[1], buf, strlen(buf)); sleep(1); // 2. 读B的返回 memset(buf, 0, sizeof(buf)); read(b_out[0], buf, sizeof(buf)); int res_b = atoi(buf); printf("B -> A %d\n", res_b); sleep(1); // 3. 给C发数据 printf("A -> C %d\n", res_b); sprintf(buf, "%d\n", res_b); write(c_in[1], buf, strlen(buf)); sleep(1); // 4. 读C的返回 memset(buf, 0, sizeof(buf)); read(c_out[0], buf, sizeof(buf)); int res_c = atoi(buf); printf("C -> A %d\n", res_c); sleep(1); // 更新current为下一次迭代的输入 current = res_c; } // 关闭剩余管道,等待子进程退出 close(b_in[1]); close(b_out[0]); close(c_in[1]); close(c_out[0]); waitpid(pid_b, NULL, 0); waitpid(pid_c, NULL, 0); return 0; }
注意事项
- 编译运行前需要确保B、C程序的可执行文件命名为
./b和./c,和代码中execlp的路径保持一致,也可以自行修改为B、C的实际存储路径 - 如果B、C的输出不带换行,可以在代码中调整读逻辑,按固定字节数读取即可
- 随机数的取值范围可以通过修改
rand() % 100的参数按需调整
内容的提问来源于stack exchange,提问作者zweinstein158
相关产品推荐
相关产品推荐

