C语言实现shell时SIGCONT无法重启停止进程但fg命令可正常恢复
问题根因
当你按下Ctrl+Z给前台进程发送SIGTSTP信号时,内核会自动将该进程从终端的前台进程组移除,你的shell成为新的前台进程组持有者。
- 单独发送
SIGCONT信号只会让停止的进程恢复可运行状态,但它依然属于后台进程组,只要它尝试读写终端,内核就会立刻给它发SIGTTIN/SIGTTOU信号让它再次停止,所以会看起来没有重启成功。 - 你的shell的
fg命令在发送SIGCONT之前,会先调用tcsetpgrp()系统调用,把目标进程的进程组设置为终端的前台进程组,进程恢复后有权限操作终端,所以可以正常运行。
修复方案
你需要在给停止的进程发SIGCONT之前,先完成终端前台权限的移交:
- 首先获取目标进程的进程组ID,调用
getpgid(pid)即可获取 - 调用
tcsetpgrp(STDIN_FILENO, 目标进程组ID),把终端前台权限交给目标进程组 - 再发送
kill(目标进程组ID, SIGCONT)信号,注意最好给整个进程组发信号,避免漏发关联的子进程 - 等目标进程运行结束或者再次停止后,再调用
tcsetpgrp(STDIN_FILENO, getpgrp())把前台权限收回到你的shell进程组
注意事项
- 调用
tcsetpgrp的时候,你的shell本身可能会收到SIGTTOU信号,需要提前给SIGTTOU设置忽略处理,否则你的shell自身会被停止 - 如果是不需要操作终端的后台进程,单独发SIGCONT可以正常运行,只有需要和终端交互的进程才需要移交前台权限
内容的提问来源于stack exchange,提问作者Saad Haider
相关产品推荐
相关产品推荐

