0

我正在尝试重写执行类似 ls|wc|wc 的 ac 程序,我已经为 ls|wc 做过,它工作正常,但我无法弄清楚为什么我的程序在指示行中的子节点处停止。请帮忙!

int main (void)
{
    pid_t pid_fils, pid_pfils;

    int fd[2], fd2[2];

    if(pipe(fd)==-1 || pipe(fd2)==-1)
    {
        printf("pipe failed!");
        return 1;
    }

    printf("program started\n");
    pid_fils=fork();
    if(pid_fils==0)
    {
        pid_pfils=fork();
        if(pid_pfils==0)
        {
            //action3
            printf("I am the grandson\n");
            close(fd[0]);//close read side
            dup2(fd[1],1);//connect write with stdout
            close(fd[1]);//close write side
            execlp("ls","ls",(char*)0);
            //execvp("ls",argv3);
            return 0;/*actions grandson*/
        }
        else
        {
            //action2
            printf("I am the son\n");
            wait();
            printf("son, wait ok\n");
            >close(fd[1]);  //close read side
            >dup2(fd[0],0); //connect write with stdin
            >close(fd[0]);  //close read side

            ///////pipe2////
           > close(fd2[0]);  //close read side
            >dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/
            printf("ok!\n");    
            >close(fd2[1]);  //close write side

            execlp("wc","wc",(char*)0);
            printf("error exec returned!\n");    
            return 0;
        }
    }
    else
    {
        ///action1
        printf("I am the parent\n");
        wait();
        printf("parent,wait ok\n");
        close(fd2[1]);  //close write side, 
        dup2(fd2[0],0); //connect read with stdin
        close(fd2[0]);  //close read side
        execlp("wc","wc",(char*)0);
        return 0;/*the parent*/
    }
    return 1;
}
4

2 回答 2

3

确保关闭所有未使用的描述符。在您的情况下,最简单的解决方案是将 pipe(fd) 的创建移动到第一个 if 块中(在第一个子进程中)。问题是只要任何进程都可能写入管道,阅读器就不会得到 EOF,因此不会终止。

if(pipe(fd2)==-1)
{
    printf("pipe failed!");
    return 1;
}

printf("program started\n");
pid_fils=fork();
if(pid_fils==0)
{
    if(pipe(fd)==-1)
    {
        printf("pipe failed!");
        return 1;
    }
    pid_pfils=fork();

我还应该提到,您可能需要重新考虑等待电话。不确定您打算对它们做什么,但您不希望“ls”进程阻止输出,因为尚未启动阅读器。

于 2013-01-12T00:16:03.580 回答
1
dup2(fd2[1],1);

上面的行将首先关闭描述符 1 处的文件,然后将描述符从 fd2[1] 复制到 1。

1 是标准输出。这意味着调用关闭标准输出。

printf 打印到标准输出,这意味着 printf 打印到现在分配给管道 fd2 的 1

所以你的确定进入管道而不是屏幕上。

尝试

        //action2
        printf("I am the son\n");
        wait();
        printf("son, wait ok\n");
        close(fd[1]);  //close read side
        dup2(fd[0],0); //connect write with stdin
        close(fd[0]);  //close read side

        ///////pipe2////
        int my_terminal_out = dup(1);
        close(fd2[0]);  //close read side
        dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/
        fprintf(my_terminal_out, "ok!\n");    
        close(fd2[1]);  //close write side

未测试。此外,您应该测试其余代码是否存在类似的错误。

+ DrC 所说的。

于 2013-01-12T00:17:29.763 回答