【问题标题】:Pipe and I/O Redirection in CC 中的管道和 I/O 重定向
【发布时间】:2016-03-31 18:08:57
【问题描述】:

请考虑以下代码:

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

#define READ 0
#define WRITE 1

int fd[2];

void execute(char*[], int mode);

int main()
{
char * command1[3] = {"cat", "output.txt", NULL};
char * command2[3] = {"wc", "-l", NULL};

pipe(fd);                       // creating pipe...


execute(command1, WRITE);               // execute command1 and write output to pipe
execute(command2, READ);                // execute command2 and get output from pipe


return 0;
}

//....................... DEFINATION .......................

void execute(char* command[], int mode)
{
pid_t pid;

pid = vfork();
if(pid == 0)
{
    if(mode == WRITE)               // writes successfully to the pipe...
    {
        close(1);
        dup(fd[WRITE]);
        close(fd[READ]);
        close(fd[WRITE]);

        execvp(command[0], command);
    }

    else if(mode == READ)               // doesnot read from the pipe and goes to the wait state...
    {
        close(0);
        dup(fd[READ]);
        close(fd[WRITE]);
        close(fd[READ]);

        execvp(command[0], command);
    }
}

else if(pid > 0)
{
    wait(NULL);
}

}

我正在尝试编写一个程序,该程序使用管道将第一个进程的标准输出重定向为第二个进程的标准输入。但我面临一个问题。上面的代码执行了第一个命令“command1”并成功将数据写入管道。但是第二个命令“command2”不会从管道中读取数据,而是进入某种等待/阻塞状态。我不知道问题是什么。如果写入管道成功,为什么从管道读取不成功?

非常感谢您的帮助。提前谢谢!!!

【问题讨论】:

  • man vfork: vfork() 函数与 fork(2) 具有相同的效果,除了如果 vfork() 创建的进程修改了除pid_t 类型的变量用于存储来自 vfork() 的返回值,或从调用 vfork() 的函数返回,或在成功调用 _exit(2) 或 exec(3) 系列之一之前调用任何其他函数 为什么你现在曾经使用vfork()
  • @EOF 高效,不复制父进程的地址空间。如果你想在 child 中执行 exec() 操作,最好使用 vfork ......无论如何我也使用了 fork 命令,它给出了相同的结果......
  • 您可能认为vfork() 更“高效”,但也更难正确使用。特别是,您没有正确使用它,因此您的程序表现出未定义的行为
  • 现在,vfork 并没有比 fork 效率高多少(fork 已经优化了很多年)。 vfork 只是被认为是过时的。
  • 不要使用dup;使用dup2dup2(fd[WRITE], STDOUT_FILENO); 完成 close(STDOUT_FILENO); dup(fd[WRITE]); 但不依赖 STDOUT_FILENO 是编号最小的未使用 fd。几十年前,Unix 添加了dup2 是有原因的。

标签: c operating-system


【解决方案1】:

由于父级没有关闭管道的 WRITE 部分,读取器被阻塞等待永远不会到来的数据(父级正在等待他被阻塞的子级)。

只需在调用execute 函数之间添加对close(fd[WRITE]); 的调用即可。

注意始终关闭未使用的管道末端...

您也可以不以这种方式调用wait(您的子进程一个接一个地执行),在调用execute 之后将调用移至wait(调用等待两次)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 2010-10-22
    • 2010-09-08
    相关资源
    最近更新 更多