首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >dup2()和exec()

dup2()和exec()
EN

Stack Overflow用户
提问于 2011-02-13 06:46:02
回答 4查看 5.5K关注 0票数 5
代码语言:javascript
复制
#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代码如下:

代码语言:javascript
复制
#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)将子进程的输出重定向到管道,让父进程从管道读取并将其打印到stdout。

我可以将子进程输出( "printf")从stdout重定向到管道,但不能将execlp的子进程xterm的输出重定向到管道。

有人能帮我吗?

EN

回答 4

Stack Overflow用户

发布于 2011-02-13 07:48:21

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

您的程序所做的是将xterm输出连接到管道,并尝试读取该输出。但xterm是一个图形用户界面程序,它通常不会将数据写入其输出。也许你真正想要实现的目标并不是很清楚。

如果删除xterm部件,它将按预期工作,也就是说,父流程将看到sample_a写入输出的内容。

代码语言:javascript
复制
        execlp("./sample_a", "./sample_a", (char *) 0);
票数 4
EN

Stack Overflow用户

发布于 2011-02-13 10:10:03

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

代码语言:javascript
复制
execlp("xterm", "xterm", "-e", "/bin/sh", "-c", "./sample_a 2>somewhere", 0);

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

票数 1
EN

Stack Overflow用户

发布于 2011-09-20 09:52:17

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

一种建议的方法(为了简洁而不进行错误检查)是

代码语言:javascript
复制
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

代码语言:javascript
复制
main(int argc, char** argv) {
   int fd = atoi(argv[1]);
   write(fd, buf,sizeof(buf));
}     

我不知道为什么dup2不能与xterm一起工作,但是这个变通方法解决了这个问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4981113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档