在bash中,当我运行立即想要标准的wc &
或cat &
之类的命令时,它会立即返回
[1] +停止的猫
这是如何实现的?如何停止我开始使用exec的程序,以及如何知道首先停止这些程序?有没有办法告诉这些程序需要stdin?
谢谢!
PS也是,+约是什么?我一直在想,但谷歌真的很难......答案 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)
函数用于获取/设置前台进程 控制终端组。
所以你想做的是:
当您创建新管道时,请调用setpgid()
将管道的所有成员放入新的流程组(管道中第一个流程的PID作为PGID)。
使用tcsetpgrp()
来管理哪个进程组位于前台 - 如果您使用&
在后台放置管道,则应该使shell自己的进程组再次成为前台进程组
使用waitpid()
和WNOHANG
标记调用WUNTRACED
以检查子进程的状态 - 这将在SIGTSTP
停止时通知您,这将允许您打印像bash这样的消息。
答案 3 :(得分:0)
如果没有时间和优先级限制,您可以在分叉子进程中使用system("command &")
,然后手动将其退出。