【问题标题】:result of child process's exection of some system command can't send to the father process with pipe子进程执行某些系统命令的结果无法通过管道发送到父进程
【发布时间】:2014-12-16 18:09:05
【问题描述】:

也许这不是一个紧凑的标题,对此我感到非常抱歉:)。我尝试使用管道将子进程的标准输入/标准输出重定向到其父进程。子进程从父进程输入执行系统命令,并通过管道将执行结果返回给父进程。这里我实现了“cat -n”和“tr /a-z/ /A-Z/”,前者工作正常,但后来没有返回任何结果。这是什么原因造成的?谢谢。

#include    <sys/types.h>
#include    <sys/stat.h>
#include    <sys/ipc.h>
#include    <sys/shm.h>
#include    <unistd.h>
#include    <fcntl.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <errno.h>
#include    <string.h>
#include    <signal.h>
#include    <assert.h>
#include    <sys/sem.h>

#define ERR_EXIT(m) \
     do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    }  while( 0)


int main(int argc, char *argv[])
{

    int chi_pipe[2], par_pipe[2];
    if (pipe(chi_pipe) == -1 || pipe(par_pipe) == -1)
        ERR_EXIT("pipe error");

    /* Set O_NONBLOCK flag for the read end (pfd[0]) of the pipe. */
    if (fcntl(chi_pipe[0], F_SETFL, O_NONBLOCK) == -1) {
        fprintf(stderr, "Call to fcntl failed.\n"); exit(1);
    }

    /* Set O_NONBLOCK flag for the read end (pfd[0]) of the pipe. */
    if (fcntl(chi_pipe[1], F_SETFL, O_NONBLOCK) == -1) {
        fprintf(stderr, "Call to fcntl failed.\n"); exit(1);
    }     


    pid_t pid;
    pid = fork();
    if (pid == -1)
        ERR_EXIT("fork error");


    if (pid == 0)
    {
        close(chi_pipe[0]); // I don't read in channel 1
        close(par_pipe[1]); // I don't write in channel 2
        dup2(chi_pipe[1], STDOUT_FILENO);
        close(STDIN_FILENO);
        dup2(par_pipe[0], STDIN_FILENO);
        execlp("cat", "cat" , "-n", NULL);
        //execlp("tr", "tr" , "/a-z/", "/A-Z/", NULL);
        sleep(10);
        close(chi_pipe[1]);
        close(par_pipe[0]);
        _exit(0);
    }


    close(par_pipe[0]);
    close(chi_pipe[1]);
    while(1) {
        char input[1024];
        memset(input, 0 , 1024);
        fgets(input, 1024 ,stdin);
        write(par_pipe[1], input, strlen(input));
        char buf[3*1024];
        int count = 0;
        while (count <= 0)
            count=read(chi_pipe[0], buf, 1024*3);
        if (count >= 1)
        {
            printf("buf=%s", buf);
            printf("\n");
        }
    }   
    close(par_pipe[1]);
    close(chi_pipe[0]);
    return 0;
}

【问题讨论】:

    标签: c redirect pipe exec fork


    【解决方案1】:

    几点:

    1. 您需要执行非阻塞 I/O。您正在从文件中读取一行,然后将其写入管道。但是不能保证tr 会方便地写回翻译的那一行。它可能会等待下一条线路进来。没有适当的线路纪律。您需要做的是从文件中读取,同时写入tr(如果管道未满)并从tr(如果字节准备好)读取。或者,更准确地说,根据 fd 上数据的可用性(读取)或管道中空间的可用性(写入)。否则你会遇到死锁问题。 tr 没有写,因为它宁愿先阅读更多内容,而且它没有 EOF。您没有从 tr 读取,因为它还没有写入,所以您也不再从文件中读取。为此,您需要使用select()(或poll())。

    2. execlp 返回的唯一方法是exec 失败;在这种情况下,您不想exit(0),因为这必然是一个错误。

    【讨论】:

      猜你喜欢
      • 2016-03-19
      • 1970-01-01
      • 2011-12-22
      • 2022-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-02
      • 1970-01-01
      相关资源
      最近更新 更多