如何判断孩子是否要求stdin?我怎么告诉它阻止它?

时间:2012-02-16 05:35:40

标签: c exec fork

在bash中,当我运行立即想要标准的wc &cat &之类的命令时,它会立即返回

[1] +停止的猫

这是如何实现的?如何停止我开始使用exec的程序,以及如何知道首先停止这些程序?有没有办法告诉这些程序需要stdin?

谢谢!

PS也是,+约是什么?我一直在想,但谷歌真的很难......

4 个答案:

答案 0 :(得分:2)

如果您希望衍生程序的行为与shell的工作方式类似,请在分娩后致电setpgrp()。这将导致后台程序在其自己的进程组中运行,因此具有分离的tty。当它尝试对控制台进行I / O时,它将接收SIGTTIN或SIGTTOU信号。 SIGTTIN或SIGTTOU的默认行为是像SIGSTOP一样停止进程。

作为家长,您可以使用waitpid()WUNTRACED找出您是否已停止子流程。

答案 1 :(得分:2)

[已编辑 - 请参阅主要问题答案的其他答案]

+符号只是指当前的作业。每个命令管道(例如foo | bar | baz)都是一个作业,可以使用以%字符开头的 jobspec 来引用它。 %1是作业编号1,%+是当前作业,%-是以前的作业。

有关职位的更多信息,请参阅Bash手册的Job Control section

答案 2 :(得分:1)

setpgid()手册页介绍了其工作原理:

  

会话可以拥有控制终端。在任何时候,一个(只有   一个会话中的进程组可以是前台   终端进程组;剩下的进程组在   的背景。如果从终端产生信号(例如,   键入中断键以生成SIGINT),该信号被发送到   前台进程组。 (有关说明,请参阅termios(3)   生成信号的字符。)只有前台进程   组可以从终端read(2);如果是后台进程组   尝试从终端read(2),然后发送组   SIGTSTP信号,暂停它。 tcgetpgrp(3)和。{   tcsetpgrp(3)函数用于获取/设置前台进程   控制终端组。

所以你想做的是:

  1. 当您创建新管道时,请调用setpgid()将管道的所有成员放入新的流程组(管道中第一个流程的PID作为PGID)。

  2. 使用tcsetpgrp()来管理哪个进程组位于前台 - 如果您使用&在后​​台放置管道,则应该使shell自己的进程组再次成为前台进程组

  3. 使用waitpid()WNOHANG标记调用WUNTRACED以检查子进程的状态 - 这将在SIGTSTP停止时通知您,这将允许您打印像bash这样的消息。

答案 3 :(得分:0)

如果没有时间和优先级限制,您可以在分叉子进程中使用system("command &"),然后手动将其退出。