管道,叉和Exec的 - 双向父子进程之间的通信 [英] Pipe, Fork, and Exec - Two Way Communication Between Parent and Child Process

查看:153
本文介绍了管道,叉和Exec的 - 双向父子进程之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的操作系统级的转让要求我通过在同一程序递归调用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


  1. 写从父exec'd子

  2. 从父读书的孩子exec'd

  3. 从exec'd孩子写回父

  4. 从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆