【问题标题】:dup2() and exec()dup2() 和 exec()
【发布时间】:2011-06-26 06:01:24
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int
main( int argc, char **argv)
{
    int pfds[ 2], i;
    size_t pbytrd;
    pid_t childpid;
    char buffer[ 200];

    pipe( pfds);
    if( ( childpid = fork() ) == -1)
    {
            perror( "fork error: ");
            exit( 1);
    }
    else if( childpid == 0)
    {
            close( pfds[ 0]);
            dup2( pfds[1], 1);
            close( pfds[ 1]);
            for( i = 0; i < 10; i++)
               printf("Hello...");
            execlp( "xterm","xterm","-e","./sample_a", (char *) 0);
            exit( 0);
}
else
{

        close( pfds[ 1]);
        for( ; ; )
        {
            if( ( pbytrd = read( pfds[ 0], buffer, sizeof( buffer) ) ) == -1)
            {
                perror(" read error: ");
                exit( 1);
            }
            else if( pbytrd == 0)
            {

                write( fileno( stdout), "Cannot read from pipe...\n", strlen( "Cannot read from pipe...\n") );
                exit( 0);
            }
            else
            {
                write( fileno( stdout), "MESSAGE: ", strlen( "MESSAGE: ") );
                write( fileno( stdout), buffer, pbytrd);
            }
        }       
}   
return( 0);

}

我的 sample_a.c 代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int
main( int argc, char **argv)
{
        int i;
        for( i= 0; i< 10; i++)
        write( fileno( stdout), "Hello...", strlen( "Hello...") );
    return( 0);
 }

在上面的代码中,我真正想做的是: 1) 将子进程的输出重定向到管道,并让父进程从管道中读取并将其打印到标准输出。

我能够将子进程输出(“printf”)从标准输出重定向到管道,但我无法将 execlp 的子进程 xterm 输出重定向到管道。

谁能帮帮我?

【问题讨论】:

    标签: c exec parent-child pipe dup2


    【解决方案1】:

    一旦你创建了一个 xterm 窗口,pipeFD 数组就存储了 in 和 out 两个文件描述。子进程不知道在哪里写。所以你可以使用dup2:

    dup2(pipeFD[1],100);
    close(pipeFD[1]);
    

    它将旧的写入端口映射到新端口(其他数字也可以)。在 xterm 中,您可以通过

    写入管道
    write(100,"something you wanna to write").
    

    【讨论】:

      【解决方案2】:

      我也遇到过类似的情况。我的目标是从在 xterm 中运行的子进程发送一些信息。如前所述,我无法使用 dup2。解决方法是将 fd 作为 xterm args 传递给新的二进制文件。

      建议的方法(为简洁起见不进行错误检查)是

      if (childpid  == 0)
      {
          /* child closes read*/
          close(pipeFD[0]);
          char writeFD[10]; // do consider space for '\0'
          /* Extract the write fd and put it in a char buffer 
             make compatible as per execlp args */
          sprintf(writeFD, "%d", pipeFD[1]); 
          /* just pass the writeFD as an arg */
          execlp("xterm", "xterm", "-e", "./binary", writeFD, (char *) 0))
      
      }
      else
      {
          /* parent closes write */
          close(pipeFD[1]);
          if((bytesRead = read(pipeFD[0], buf, SIZE)) != -1)
          {
              printf("Recieved %s\n", buf);
              close(pipeFD[0]);
          }
       }
      

      在xterm中运行的子进程上,提取fd

      main(int argc, char** argv) {
         int fd = atoi(argv[1]);
         write(fd, buf,sizeof(buf));
      }     
      

      我不知道为什么 dup2 不能与 xterm 一起使用,但这种解决方法可以解决要求。

      【讨论】:

        【解决方案3】:

        xterm 没有输出,因此无法将其重定向到任何地方。 xterm 运行一个子进程并将子进程的输出重定向到它自己,因此如果您想将子进程的输出重定向到 xterm 以外的其他位置,您需要在子进程中自己执行此操作,在 xterm 启动它之后。最简单的方法可能是让 xterm 启动一个 shell 并使用 shell 重定向。要为孩子重定向 stderr,您可以使用以下内容:

        execlp("xterm", "xterm", "-e", "/bin/sh", "-c", "./sample_a 2>somewhere", 0);
        

        用适当的东西替换somewhere。假设你想在你的原始程序中捕获它,你可能想用 tempnam(3) 和 mkfifo(3) 创建一个临时 fifo 并打开它以便在你的父程序中读取。你需要在 fork 之前创建它并在 fork 之后打开它,因为 open 会阻塞,直到 shell 运行并打开写入端。打开完成后,您可以删除该fifo,并从现在未命名的fifo中读取。

        【讨论】:

          【解决方案4】:

          xterm 是一个终端模拟器。它执行您提供的程序 (sample_a),将其输入和输出连接到自身,以便程序在其标准输入中接收用户输入,并将其发送到其标准和错误输出的任何内容打印给用户。

          您的程序正在做的是将xterm 输出连接到管道,并尝试读取它。但是xterm 是一个 GUI 程序,它通常不会将数据写入其输出。也许您并不清楚您到底想要达到什么目的。

          如果您删除xterm 部分,它应该可以按预期工作,即父进程将看到sample_a 写入输出的内容。

                  execlp("./sample_a", "./sample_a", (char *) 0);
          

          【讨论】:

          • 我同意,如果我删除 xterm 部分,它将起作用。这是我在一个大学网站上看到的一个编程问题。练习是在 xterm 窗口上接受用户的输入并在 xterm 上显示输出,但任何错误(perror)都应打印到调用它的终端窗口。那么 xterm 无法与终端窗口进行通信吗?实际上这是大问题的一小部分(5-6页问题)。希望这会有所帮助
          猜你喜欢
          • 2016-02-26
          • 2015-07-03
          • 1970-01-01
          • 1970-01-01
          • 2017-09-05
          • 1970-01-01
          • 2021-07-23
          • 1970-01-01
          相关资源
          最近更新 更多