我的操作系统类中的作业要求我通过在同一程序上递归调用 exec 来构建二进制进程树。目标是将某些任意任务拆分为单独的进程。父级应与子级通信,子级应仅通过无名管道与父级通信。这个想法是,父级向每个子级发送一半的工作,并且递归地继续,直到满足基本情况,其中传递给每个子级的字符串的长度
为了更好地理解如何使用 c 中的管道进行双向通信,我在继续实际作业之前创建了以下简单程序。但父进程永远不会从子进程读取数据。我期待输出...
在父|收到消息:测试
相反,当我打印时我得到...
在父|收到消息:
看起来 buff 是空的并且没有从子进程中读取。有人可以解释一下我做错了什么和/或标准方法吗
- 从父级写入执行子级
- 从执行子进程中的父进程读取
- 从执行的孩子写回父母
- 从父级中的 exec'd 子级读取
我需要使用 exec()、pipe()、fork()。谢谢。
/**
* *********************************
* two_way_pipes.c
* *********************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define PARENT_READ read_pipe[0]
#define PARENT_WRITE write_pipe[1]
#define CHILD_WRITE read_pipe[1]
#define CHILD_READ write_pipe[0]
#define DEBUGGING 1
int main(int argc, char **argv) {
char buff[5];
// in the child process that was exec'd on the orginal call to two_way_pipes
if(argc == 2) {
read(STDIN_FILENO, buff, 4); // this should read "test" from stdin
buff[4] = '\0';
fprintf(stdout, "%s\n", buff); // this should right "test" to stdout and be read by the parent process
// int the root process, the original call to two_way_pipes with no args
} else {
int pid;
int read_pipe[2];
int write_pipe[2];
pipe(read_pipe);
pipe(write_pipe);
pid = fork();
// parent process
if(pid > 0) {
close(CHILD_READ);
close(CHILD_WRITE);
write(PARENT_WRITE, "test", 4); // attempting to write this to the child
struct timeval tv;
fd_set readfds;
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(PARENT_READ, &readfds);
select(PARENT_READ + 1, &readfds, NULL, NULL, &tv);
if(FD_ISSET(PARENT_READ, &readfds)) {
read(PARENT_READ, buff, 4); // should read "test" which was written by the child to stdout
buff[4] = '\0';
close(PARENT_READ);
close(PARENT_WRITE);
fprintf(stderr, "in parent | message received: %s\n", buff); // "test" is not in buff
}
// child process
} else if(pid == 0) {
close(PARENT_READ);
close(PARENT_WRITE);
dup2(CHILD_READ, STDIN_FILENO);
dup2(CHILD_WRITE, STDOUT_FILENO);
close(CHILD_READ);
close(CHILD_WRITE);
char *argv2[] = {"some random arg to make sure that argc == 2 in the child", NULL};
execvp("two_way_pipes", argv2);
_exit(0);
// error forking child process
} else {
fprintf(stderr, "error forking the child\n");
}
}
}
Update
根据 Jonathon 的回答,我修改了传递给 execvp 的 arg2 数组以......
char *argv2[] = {"two_way_pipes", "1", NULL};
execvp("two_way_pipes", argv2);
这并没有解决问题。家长仍然无法从客户端读取“测试”。然而,为了回应 Jonathon 的回答和 William 的评论,我开始调整我的 exec 调用,并出于某种原因将其更改为下面的行显示。
execl("two_way_pipes", "two_way_pipes", "1", NULL);
我很乐意接受任何解释为什么 execvp 调用不起作用但 execl 调用起作用的答案。