首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用execvp时出现输入重定向问题?

使用execvp时出现输入重定向问题?
EN

Stack Overflow用户
提问于 2011-04-10 14:38:07
回答 3查看 3.5K关注 0票数 1

我已经实现了一个简单的程序,它使用简单的管道和execvp调用来模拟$ls -l | wc -c命令的执行。

现在,在重定向stdin和stdout之后,当执行程序时,shell提示符消失,并等待按enter键。

任何解决这个问题的方法。请也批评我的代码..

谢谢

代码语言:javascript
复制
 /* Create pipe */
  ret_val=pipe(pipe_fd);
  /*Error check */
   if(ERROR==ret_val)
   {
    perror("Pipe creation error \n");
    _exit(FAILURE);
   }

/*Fork First Child */
pid_one = fork() ;

if( 0 == pid_one ) /*child process block */
{


    /* First sub process */
    /*printf("First sub process is %d \n",getpid());*/

    /* redirect stdout to pipe's write end  for sub process one*/
    dup2(pipe_fd[1],1);


    /*close pipe read end */
    close(pipe_fd[0]);

    execvp(cmd_one_tokens[0],cmd_one_tokens);   

    /* if execvp returns then if must have failed */
    printf("Unknown Command \n ");
    //exit(10);
}
else /*main process block */
{
    /*printf(" Main  process is %d \n",getpid());*/

    /*Wait for first sub process to finish */
    //wait(&status);

    /*printf("Exit status of first child is %d \n ", WEXITSTATUS(status) );*/

    /*Fork second subprocess */
    pid_two = fork();

    if( 0 == pid_two ) /*second child process block */
    {
        /* redirect stdin  to pipe's read end  for sub process two */
        dup2(pipe_fd[0],0);

    //  close(0);       /* close normal stdin */
        //  dup(pipe_fd[0]);   /* make stdib same as pfds[0] */


        /*close pipe write end */
        close(pipe_fd[1]);

        /* Second  sub process */
        /*printf("Second sub process is %d \n",getpid()); */

        execvp(cmd_two_tokens[0] , cmd_two_tokens); 
        /* if execvp returns then if must have failed */
        printf("Unknown Command \n ");

    }
    else        /*main process block */
    {
        /* printf(" Main  process is %d \n",getpid()); */
        status=-1; /*reset status */

        /*Waiting for the second sub process to finish in No hang fashion */
            waitpid ( -1 , &status ,WNOHANG);
        /*printf("Exit status of second  child is %d \n ", WEXITSTATUS(status) ); */

    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-04-10 15:33:28

在派生第二个进程之后,必须关闭主进程中的管道文件描述符。在关闭它们之前,子进程(wc)将等待主进程仍处于打开状态的管道上的输入。你必须非常小心地把所有不需要的管子末端都封闭起来。

票数 2
EN

Stack Overflow用户

发布于 2011-04-10 15:07:32

您的代码没有完成您所描述的您想要做的事情:

您创建了一个管道,派生了一个新进程,将它的stdout重定向到管道并让它执行某个程序(到目前为止还不错),然后在父进程中等待您的子进程完成,然后才派生第二个进程,将它的stdin重定向到管道的另一端,并让它执行另一个程序。

这不是"ls | wc“所做的--在shell中,它们是并发运行的。删除第一个wait()。

票数 1
EN

Stack Overflow用户

发布于 2011-04-10 15:20:05

pid_one = fork();if( 0 == pid_one ) /*child进程块*/

您不会检查fork(2)是否返回错误,这是一种非常真实的可能性。(用户可能会遇到RLIMIT_NPROC限制、kernel.threads-max、用于保存任务结构的内存不足等问题)

更常用的fork(2)用法如下所示:

代码语言:javascript
复制
if(-1 == (pid = fork()) {
    perror("fork");
    exit(1); /* or return -1 or similar */
} else if (0 == pid) {
    /* executing as child */
} else {
    /* parent, pid is child */
}

execvp(cmd_two_tokens,cmd_two_tokens);/*如果execvp返回则if一定失败*/ printf(“未知命令\n ");

请注意,execvp(3)失败的原因有很多;简单地打印“未知命令”可能会让您的用户在将来非常困惑。最好是调用perror("execvp");,让您的用户有机会发现execvp(3)调用失败的真正原因。

waitpid ( -1,&status,WNOHANG)

在这里使用WNOHANG可能是危险的;如果系统正在“恰到好处”地运行,那么您的父母甚至可能在孩子还没有机会开始执行之前就访问了这段代码。因为您已经要求在没有孩子退出的情况下立即返回它,所以当孩子最终退出时,孩子可能会变成僵尸--您的代码不会抓住机会再次等待孩子。

我不确定最好的解决方案是什么:如果你使用SA_NOCLDWAIT to sigaction(2)来避免完全创建僵尸,你将永远没有机会收集孩子的退出状态。安装SIGCHLD信号处理程序可能会干扰进程的其余部分;您的客户端可能有理由自己设置它。使用阻塞waitpid(2)可能会在其他地方停止处理。使用非阻塞waitpid(2)意味着您仍然需要在某个时候收集孩子的状态,可能是通过轮询。(但在这种情况下,您不能对pid使用-1,因为您可能会意外地收获另一个子进程。)

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

https://stackoverflow.com/questions/5610184

复制
相关文章

相似问题

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