2013-07-09 81 views
2

我有以下通过fork和execvp执行命令的函数。我在fork中启动的脚本正在侦听输入数据。我如何发送数据到myscript?如何写入管道叉?

int external_command() 
{ 

    int pfds[2]; 
    if (pipe(pfds) < 0) 
     return -1; 

    if ((uproc.pid = fork()) == -1) 
     return -1; 

    if (uproc.pid == 0) { 
     /* child */ 

     const char *argv[4]; 
     int i = 0; 
     argv[i++] = "/bin/sh"; 
     argv[i++] = "myscript.sh"; 
     argv[i++] = NULL; 

     close(pfds[0]); 
     dup2(pfds[1], 1); 
     close(pfds[1]); 

     execvp(argv[0], (char **) argv); 
     exit(ESRCH); 

    } else if (uproc.pid < 0) 
     return -1; 

    /* parent */ 
    close(pfds[1]); 

    int status; 
    while (wait(&status) != uproc.pid) { 
     DD("waiting for child to exit"); 
    } 

    char buffer[64]; 
    ssize_t rxed; 
    char *c; 
    int t; 

    //read from fork pipe 
    *value = NULL; 
    while ((rxed = read(pfds[0], buffer, sizeof(buffer))) > 0) { 
     if (*value) 
      t = asprintf(&c, "%s%.*s", *value, (int) rxed, buffer); 
     else 
      t = asprintf(&c, "%.*s", (int) rxed, buffer); 

     if (t == -1) return -1; 

     free(*value); 
     *value = strdup(c); 
     free(c); 
    } 
    // how to write to the pipe fork? 
} 
+0

您检查'fork'的返回* *为负值*。 –

+0

文件描述符的重复也让我怀疑。 – trojanfoe

+0

代码'} else if(uproc.pid <0)返回-1;'根本不需要'else';你已经涵盖了这种情况。 –

回答

2

管道是单向的。调用pipe两次,以获得一对文件描述符来读取孩子的数据(如你已经有的),另一个将数据发送给孩子(这将是新的)。您需要像现在这样做dup2close魔法,以便将该新管道设置为孩子的stdin。

+0

你能编辑我的代码吗? – MOHAMED

+0

所以我必须定义'int pfds [3];'。然后在这个孩子中:'dup2(pfds [2],0);关闭(工艺流程图[2])'。然后在父类中,我使用'pfds [0]'调用写入。这样对吗? – MOHAMED

2

我想你的意思是说你想写父进程的子进程stdin?为此,您需要创建两个管道。一个在孩子中用作stdout,就像现在一样,另一个用于stdin与现在的方式非常相似(但是当然索引相反)。

当然,在孩子写信给孩子之前,你不能wait,因为如果孩子需要继续输入,你可能会发生死锁。管道的

+0

所以我必须定义'int pfds [3];'。然后在这个孩子中:'dup2(pfds [2],0);关闭(工艺流程图[2])'。然后在父类中,我使用'pfds [0]'调用写入。这样对吗? – MOHAMED

+0

@MOHAMED不,你再次调用'pipe'来创建另一组管道,并且在孩子中使用'otherpfds [0]'作为'FILENO_STDIN'。 –

0

基础

所以你学习你在这种情况下做

int fd[2]; /*write(fd[1],buffer,strlen) 
      /read(fd[0],buffer2,SIZE)*/ 
pid_t cpid; 

if(pipe(fd)==-1){ 
    perror("pipe"); 
    exit(EXIT_FAILURE); 
} 
if((cpid=fork())<0){/* FORK INIT */ 
    printf("\n\tFORK ERROR\n"); 
    exit(1); 
} 
if(cpid==0){   /*SON*/ 
    close(fd[0]); 
    /********CODE******/ 
    if((write(fd[1],final2,strlen(final2)))<0){ 
     perror("\n\tWRITE ERROR"); 
    } 
    close(fd[1]); 
}else{     /*FATHER*/ 
    close(fd[1]); 
    if((read(fd[0],aler,NN))<0){ 
     perror("\n\tREAD ERROR"); 
    } 
    wait(NULL); 
    /********CODE******/ 
    close(fd[0]); 
} 

什么父进程(父亲)请研究这段代码新(儿子阅读()信息)工艺

如果你想

双向读()写()创建2个管道(FD1 [2],FD2 [2])

使用相同的逻辑如上述,父读取,关闭写入结束FD1 [1],儿子写入,关闭读端FD1 [0]

反之亦然到另一个方向

爸爸写,关闭该读取结束fd2 [0],儿子读取,关闭写入结束fd2 [1]