[英]How can I tell if a child is asking for stdin? How do I tell it to stop that?
在bash中,当我运行像wc &
或cat &
这样的命令并立即想要标准时,它会立即返回
[1] +停止了猫
这是如何完成的? 如何停止我开始使用exec的程序,以及如何知道首先停止这些程序? 有没有办法告诉这些程序是否需要标准输入?
谢谢!
PS也,+约是什么? 我一直在想,但谷歌真的很难......
如果您希望衍生程序的行为与shell的工作方式类似,请在分叉您的孩子后调用setpgrp()
。 这将导致后台程序在其自己的进程组中运行,因此具有分离的tty。 当它尝试对控制台进行I / O时,它将接收SIGTTIN或SIGTTOU信号。 SIGTTIN或SIGTTOU的默认行为是像SIGSTOP一样停止进程。
作为父级,您可以使用waitpid()
和WUNTRACED
找出是否已停止子进程。
[已编辑 - 请参阅主要问题答案的其他答案]
+
号只是指当前的工作 。 每个命令管道(例如foo | bar | baz
)都是一个作业,可以使用以%
字符开头的jobspec来引用。 %1
是作业编号1, %+
是当前作业, %-
是上一个作业。
有关作业的更多信息,请参阅Bash手册的“ 作业控制”部分 。
setpgid()
手册页解释了它的工作原理:
会话可以具有控制终端。 在任何时候,会话中的一个(并且只有一个)进程组可以是终端的前台进程组; 其余进程组在后台。 如果从终端生成信号(例如,键入中断键以生成
SIGINT
),则将该信号发送到前台进程组。 (有关生成信号的字符的说明,请参阅termios(3)
。)只有前台进程组可以从终端read(2)
; 如果后台进程组试图从终端read(2)
,则向该组发送SIGTSTP
信号,该信号将其挂起。tcgetpgrp(3)
和tcsetpgrp(3)
函数用于获取/设置控制终端的前台进程组。
所以你想要做的是:
创建新管道时,调用setpgid()
将管道的所有成员放入新的进程组(管道中第一个进程的PID作为PGID)。
使用tcsetpgrp()
来管理哪个进程组在前台 - 如果你在后台放置一个带有&
的管道,你应该让shell自己的进程组再次成为前台进程组。
使用WNOHANG
和WUNTRACED
标志调用waitpid()
来检查子进程的状态 - 这将在SIGTSTP
停止时通知您,这将允许您打印类似bash的消息。
如果没有时间和优先级约束,您可以在分叉子进程中使用system("command &")
然后手动使其退出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.