管道,叉和Exec的 - 双向父子进程之间的通信 [英] Pipe, Fork, and Exec - Two Way Communication Between Parent and Child Process
问题描述
在我的操作系统级的转让要求我通过在同一程序递归调用exec建立一个二进制进程树。我们的目标是一些任意任务分成独立的进程。家长应与孩子,与家长只能通过命名管道孩子沟通。这个想法是,在父发送工作的每个子半这样下去递归直至碱情况下被满足,其中被传递给每个子字符串的长度为< = 2的子随后处理这些数据,并将结果发送回到通过管道父。
An assignment in my Operating Systems class requires me to build a binary process tree by recursively calling exec on the same program. The goal is to split some arbitrary task into separate processes. The parent should communicate with the children, and the children with the parent only via unnamed pipes. The idea is that the parent sends each child half of the work and this continues recursively until a base case is met where the length of the string being passed to each child is <= 2. The child then processes this data and sends the results back to the parent via pipes.
要获得更好的理解双向通信如何在C管我的作品在移动到实际分配之前创建下面的简单程序。家长虽然从来没有读取子进程的数据。我期待的输出...
To get a better understanding of how two way communication works with pipes in c I created the following simple program before moving on to the actual assignment. The parent never reads the data from the child process though. I'm expecting the output...
在父母|接收到消息:测试
in parent | message received: test
相反,当我打印,我得到...
Instead, when I print I get...
在父母|收到的消息:
似乎抛光轮是空的,而不是从子进程读取。是否有人可以解释我做错了和/或标准的方式
It seems that buff is empty and not reading from the child process. Can someone please explain what I'm doing wrong and/or the standard way of
- 写从父exec'd子
- 从父读书的孩子exec'd
- 从exec'd孩子写回父
- 从exec'd孩子读父
我需要使用EXEC(),管(),叉()。谢谢你。
I am required to use exec(), pipe(), fork(). Thank you.
/**
* *********************************
* 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");
}
}
}
更新
根据乔纳森的回答我修改了ARG2数组被传递到execvp到...
Based on Jonathon's answer I modified the arg2 array being passed into execvp to...
char *argv2[] = {"two_way_pipes", "1", NULL};
execvp("two_way_pipes", argv2);
这并没有解决问题。父仍然是无法读取测试从客户端返回。但是,在回应乔纳森的回答和威廉的评论我开始调整我的exec调用由于某种原因将其更改为线图如下工作。
This didn't fix the issue. The parent still wasn't able to read "test" back from the client. However, in response to Jonathon's answer and William's comment I started tweaking my exec call and for some reason changing it to the line show below worked.
execl("two_way_pipes", "two_way_pipes", "1", NULL);
我会很乐意接受解释为什么execvp调用是行不通的任何答案,但电话execl的那样。
I'll gladly accept any answers explaining why the execvp call wouldn't work but the execl call did.
推荐答案
提到的问题通过的Jonathon莱因哈特的,最有可能调用 execv()
失败。
要测试这个修改这些行
execvp("two_way_pipes", argv2);
_exit(0);
是
...
#include <errno.h>
...
execvp("two_way_pipes", argv2); /* On sucess exec*() functions never return. */
perror("execvp() failed); /* Getting here means execvp() failed. */
_exit(errno);
希望收到
execvp() failed: No such file or directory
要解决这个变化。
execvp("two_way_pipes", argv2);
是
execvp("./two_way_pipes", argv2);
此外,如果孩子不是 EXEC *()
ED那么这行
read(PARENT_READ, buff, 4); // should read "test" which was written by the child to stdout
失败,反过来 BUFF
将不会被初始化,因此该行
fails and in turn buff
is not initialised and therefore this line
fprintf(stderr, "in parent | message received: %s\n", buff);
引发未定义的行为。
provokes undefined behaviour.
要解决这个问题,至少正确初始化 BUFF
通过更改
To fix this at least properly initialise buff
by changing
char buff[5];
是
char buff[5] = "";
这篇关于管道,叉和Exec的 - 双向父子进程之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!