将exec输出重定向到缓冲区或文件

dev*_*vin 40 c fork exec

我正在写一个C程序中我fork(),exec()wait().我想把我执行的程序的输出写入文件或缓冲区.

例如,如果我exec ls 我想写入file1 file2 etc缓冲区/文件.我认为没有办法读取标准输出,所以这是否意味着我必须使用管道?这里有一个我无法找到的一般程序吗?

R S*_*hko 86

用于将输出发送到另一个文件(我要忽略错误检查以关注重要细节):

if (fork() == 0)
{
    // child
    int fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

    dup2(fd, 1);   // make stdout go to file
    dup2(fd, 2);   // make stderr go to file - you may choose to not do this
                   // or perhaps send stderr to another file

    close(fd);     // fd no longer needed - the dup'ed handles are sufficient

    exec(...);
}
Run Code Online (Sandbox Code Playgroud)

要将输出发送到管道,您可以将输出读入缓冲区:

int pipefd[2];
pipe(pipefd);

if (fork() == 0)
{
    close(pipefd[0]);    // close reading end in the child

    dup2(pipefd[1], 1);  // send stdout to the pipe
    dup2(pipefd[1], 2);  // send stderr to the pipe

    close(pipefd[1]);    // this descriptor is no longer needed

    exec(...);
}
else
{
    // parent

    char buffer[1024];

    close(pipefd[1]);  // close the write end of the pipe in the parent

    while (read(pipefd[0], buffer, sizeof(buffer)) != 0)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你写道:"close(pipefd [1]); //不再需要这个描述符".为什么? (6认同)

Jon*_*ler 15

你需要准确地决定你想做什么 - 最好更清楚地解释一下.

选项1:文件

如果您知道要执行的命令的输出要转到哪个文件,则:

  1. 确保父母和孩子就名称达成一致(父母在分叉前决定姓名).
  2. 父叉 - 您有两个流程.
  3. Child重新组织事物,以便文件描述符1(标准输出)转到文件.
  4. 通常,您可以单独留下标准错误; 您可以从/ dev/null重定向标准输入.
  5. 然后孩子执行相关命令; 所述命令运行并且任何标准输出都转到该文件(这是基本的shell I/O重定向).
  6. 执行过程然后终止.
  7. 同时,父进程可以采用以下两种主要策略之一:
    • 打开文件进行阅读,并继续阅读直到达到EOF.然后需要仔细检查孩子是否死亡(因此不会再有任何数据可读),或者等待孩子的更多输入.
    • 等待孩子死亡,然后打开文件进行阅读.
    • 第一个的优点是父母可以在孩子也在跑的时候做一些工作; 第二个优点是您不必使用I/O系统(重复读取过去的EOF).

选项2:管道

如果您希望父级读取子级的输出,请安排子级将其输出传递回父级.

  1. 使用popen()以简单的方式完成此操作.它将运行该进程并将输出发送到您的父进程.请注意,在子节点生成输出时父节点必须处于活动状态,因为管道具有较小的缓冲区大小(通常为4-5 KB),并且如果子节点生成的数据多于父节点未读取的数据,则子节点将阻塞直到父母读.如果父母正在等待孩子死亡,那么你就会陷入僵局.
  2. 使用pipe()等以这种方式做到这一点.Parent调用pipe(),然后调用fork.孩子对管道进行分类,以便管道的写入端是其标准输出,并确保关闭与管道相关的所有其他文件描述符.这可能会使用dup2()系统调用.然后它执行所需的进程,将其标准输出发送到管道.
  3. 同时,父母也关闭管道的不需要的末端,然后开始阅读.当它在管道上获得EOF时,它知道孩子已经完成并关闭了管道; 它也可以关闭管道的末端.