在子进程向其写入内容后,无法从管道中读取

时间:2016-09-25 00:50:12

标签: c linux pipe dup2

我创建了一个函数exec_in_child,它接受​​命令参数,管道文件描述符(fds),read_flagwrite_flag作为输入。当write_flag设置为1时,子进程应将stdout复制到fds[1],然后执行该命令。当read_flag设置为1时,子项应将stdin复制到fds[0]并执行命令。

  • 当我正在阅读/写作时,是否必须关闭管道的一端 另一端?
  • 以下代码不起作用。我正在尝试在子进程中执行/bin/ls,将stdout写入管道,然后读取 它在父进程中关闭并打印出来。我无法读入 父进程。
  • 我可以在同一进程内读取和写入管道而不关闭其他进程吗?当我想要孩子阅读时会出现这种情况 从管道,执行,然后写入管道。
#include <stdio.h> /* printf */
#include <stdlib.h> 
#include <string.h> /* strlen, strcpy */

int exec_in_child(char *arguments[], const int temp[], int , int);

int main()
{
    ssize_t bytes_read;
    char *curr_dir = (char *)malloc(500);
    int pipefd[2];

    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    char *arguments[] = {"/bin/pwd",0};
    exec_in_child(arguments, pipefd, 0, 1);
    bytes_read = read(pipefd[0], curr_dir, strlen(curr_dir));
    printf("%s = %d\n", "bytes read from pipe" ,(int)bytes_read);
    printf("%s: %s\n","character read from the pipe",curr_dir);
    return 0;
}


int exec_in_child(char * arguments[], const int fds[], int read_flag, int write_flag) {
    pid_t pid;
    pid = fork();
    if (pid < 0) {
        perror("Error: Fork Failed");
    }
    else if (pid == 0){ /*inside the child process */
        if (read_flag == 1) {
            dup2(fds[0], 0);
            perror("Dup2 stdin");
        }
        if (write_flag == 1) {
            dup2(fds[1], 1);
            perror("Dup2 stdout");
        }
        execv(arguments[0], arguments);
        perror("Error in child");
        exit(1);
    } /* if (pid == 0) */
    else {
        while(pid != wait(0));  
    } /* if(pid < 0) */

    return 0;
}

我得到了这个结果:

hmwk1-skk2142(test) > ./a.out 
Dup2 stdout: Success
bytes read from pipe = 0
character read from the pipe: 

1 个答案:

答案 0 :(得分:3)

回答你的问题:

1)您不需要关闭管道的任何一端以使用另一端。但是,您通常希望关闭您不使用的管道的任何一端。执行此操作的最大原因是管道将仅在所有打开的写入文件描述符关闭时关闭。

2)您的代码无法正常使用,因为您未正确使用strlen()。此函数通过搜索null(0)字符来计算字符串的长度。当malloc()存储curr_dir时,您无法保证其中存在的内容(尽管通常会将其归零,如本例所示)。

因此,您的调用strlen(curr_dir)返回零,read()系统调用认为您想要读取零字节数据。将您的阅读电话更改为以下内容:

bytes_read = read(pipefd[0], curr_dir, 500);

并且您的代码将完美运行。

3)您可以读取和写入您有效文件描述符的任何管道。单个进程绝对可以读取和写入相同的管道。