execv,选择和阅读

时间:2010-09-17 11:48:41

标签: c++ c unix

我正在创建一个子父级fork(),以便能够通过管道与父级(/bin/sh)进行通信。

问题是: 在父级中,我在子输出上设置了select(),但只有在进程完成时才会解锁!所以,当我说ps时,它没关系。但是当我运行/bin/sh时,它会在shell退出之前输出。但我想读它的输出!

for(;;) {
select(PARENT_READ+1,&sh,NULL,NULL,NULL); // This unblocks only when shell exits!
if (FD_ISSET(PARENT_READ,&sh)) {
   while (n = read (PARENT_READ, &buf,30)) {
       buf[30]='\0';
       printf("C: %s\n",buf);
   };
};
}

答案是禁止缓冲管道的某个领域?

1 个答案:

答案 0 :(得分:4)

许多程序根据他们是否认为他们正在与终端(tty)交谈来改变他们的行为,而shell肯定会这样做。此外,如果stdout是tty,则默认C流stderrstdout可能是无缓冲的,否则完全缓冲 - 这意味着它们在内部缓冲区已满之前不会刷新,程序显式刷新它们,或者程序结束。

要解决此问题,您必须使程序假装为终端。为此,您可以使用系统的伪终端API(尝试man 7 pty)。最终结果是一对文件描述符,它们像管道一样工作。

另外,另外,当select select unblocks时,你应该从触发的文件描述符中读取一次。如果您多次阅读,这可能是您已经到达的循环,那么您可能会在后续读取时再次出现阻塞,除非您的FD处于非阻塞模式。

但是,我不得不问:为什么你需要以这种方式与shell进行交互?是否可以,比如运行shell脚本,或者使用“/ bin / sh -c your_command_here”代替?实际上需要真正的终端正常工作的程序相对较少 - 主要是提示输入密码的程序,如sshsusudo