c - 管道、dup2 和 exec()

标签 c linux shell exec dup2

我必须编写一个可以运行管道的 shell 。例如像 ls -l | wc -l 这样的命令”。我已经成功解析了用户给出的命令,如下:

"ls" = firstcmd

"-l" = frsarg

"wc" = scmd

"-l" = secarg

现在我必须使用两个 fork ,因为命令是两个和一个管道。 我编写的用于执行该命令的代码块如下:

pid_t pid;
int fd[2];

pipe(fd);
pid = fork();

if(pid==0)
{        
    dup2(fd[WRITE_END], STDOUT_FILENO);
    close(fd[READ_END]);
    execlp(firstcmd, firstcmd, frsarg, (char*) NULL);
}
else
{ 
    pid=fork();

    if(pid==0)
    {
        dup2(fd[READ_END], STDIN_FILENO);
        close(fd[WRITE_END]);
        execlp(scmd, scmd, secarg, (char*) NULL);
    }
}

因此,当我运行 shell 并输入命令 ls -l | wc -l 时(例如)exec 的结果没有显示,但 shell 保持正常运行。

奇怪的是,只有当我用“exit”或“^C”终止 shell 时,命令的结果才会显示。

这个输出有什么问题吗?为什么我输入命令后不立即显示?

最佳答案

您需要关闭父进程和子进程中的所有管道描述符(在子进程中复制之后)。在您的代码中,主要问题是, wc 进程不会退出,因为仍然存在写入器(因为父进程尚未关闭写入端)。变化如下所示。我还在父进程中添加了 waitpid 来等待 wc 进程。

pid_t pid;
int fd[2];

pipe(fd);
pid = fork();

if(pid==0)
{
    dup2(fd[WRITE_END], STDOUT_FILENO);
    close(fd[READ_END]);
    close(fd[WRITE_END]);
    execlp(firstcmd, firstcmd, frsarg, (char*) NULL);
    fprintf(stderr, "Failed to execute '%s'\n", firstcmd);
    exit(1);
}
else
{ 
    pid=fork();

    if(pid==0)
    {
        dup2(fd[READ_END], STDIN_FILENO);
        close(fd[WRITE_END]);
        close(fd[READ_END]);
        execlp(scmd, scmd, secarg,(char*) NULL);
        fprintf(stderr, "Failed to execute '%s'\n", scmd);
        exit(1);
    }
    else
    {
        int status;
        close(fd[READ_END]);
        close(fd[WRITE_END]);
        waitpid(pid, &status, 0);
    }
}

关于c - 管道、dup2 和 exec(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44072328/

相关文章:

python - 如何使用 wget 自动执行网页浏览任务?

python - Bash 脚本与用于 Shell-Command-Heavy 实用程序的 Python 脚本的优点

c - 为什么我可以在 C 中用一个参数定义函数时调用不带参数的函数?

c++ - 为什么我不能使用 fopen?

linux - 将输出同时重定向到控制台和文件的命令在 bash 中运行良好。但我如何让它在 korn shell(ksh) 中工作

linux - 图易 : how to make flowchart?

bash - 在 shell 中实现通配符扩展

c - 扫描以 32 个十六进制值表示的 128 位输入

c - 请解释此程序中的逗号运算符

linux - 通过 rsync-daemon 复制 linux 设备文件失败