首页 > 解决方案 > fork()子执行命令奇怪地输出

问题描述

我正在尝试做 ls -la | 厕所

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
    
int main(int argc, char **argv)
{
    int pipes=3;
    char *ls[] = {"ls","-la",NULL};
    char *wc[] = {"wc",NULL};
    char *base64[] = {"base64","-w0",NULL};
    //char **commands[] = {ls,wc,base64};

    int fds[pipes][2];
    for(int i=0;i<pipes;i++)
    {
        int err = pipe(fds[i]);
        if(err == -1)
        {
            perror("Pipe failed.\n");
        }
    }
    int status;
    pid_t childPid;
    //Child 1.
    if((childPid = fork()) == 0)    
    {
        dup2(fds[0][1],1);
        for(int i=0;i<pipes;i++)
        {
            close(fds[i][0]); 
            close(fds[i][1]);
        }
        execvp(ls[0],ls);
        exit(0);
    }
    else if(childPid == -1)
    {
        perror("Child 1 failed.\n");
    }
    // Second child.
    if((childPid = fork()) == 0)
    {
        dup2(fds[0][0],0);
        for(int i=0;i<pipes;i++)
        {
            close(fds[i][0]); 
            close(fds[i][1]);
        }
        execvp(wc[0],wc);
    }
    else if(childPid == -1)
    {
        perror("Child 2 failed.\n");
    }

    for(int i=0;i<pipes;i++)
    {
        close(fds[i][0]);
        close(fds[i][1]);
    }
    waitpid(childPid,&status,WUNTRACED|WNOHANG);
    return 0;
}

出乎意料:

root@danial#gcc -o pip pip.c

root@danial#./pip

10      83     436

我得到的输出:

root@danial#./pip

根@danial# 10 83 436

光标停留在这里,直到我按下回车键。

我尝试在没有管道的情况下这样做,只是编写了一个简单的程序:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>

int main(int argc, char **argv)
{
    if(fork() == 0)
    {
        execlp("ls","ls","-la",NULL);
        exit(0);
    }
    return 0;
}

同样的事情发生了:

root@danial#./test

根@danial#total 84

drwxr-xr-x 3 根根 4096 Mar 30 06:49 。

drwxr-xr-x 9 根根 4096 Mar 29 09:33 ..

-rwxr-xr-x 1 根 16960 Mar 30 06:49 pip

-rw-r--r-- 1 根根 1310 Mar 30 06:48 pip.c

标签: cpipeforkexec

解决方案


问题是这个

waitpid(childPid,&status,WUNTRACED|WNOHANG);

WNOHANG你告诉轮询状态,waitpid然后立即返回而不实际等待。

waitpid调用返回时,您退出父进程,使您的两个子进程成为孤立的。

当父进程退出时会发生什么是它的父进程(shell)接管并打印提示。然后你的子进程打印他们的输出。您按下以“清除”输出的Enter键只是 shell 的空输入。

您需要等待您的两个子进程。


推荐阅读