我正在尝试写一个外壳。在运行前台进程时,分叉进程管道将被赋予自己的进程组id。然后,终端被交给这个进程组id (使用tcsetpgrp),外壳等待它终止,然后再给自己终端控制。这个很好用。
出现的问题是当我试图运行后台进程时。同样,我给管道中的所有进程一个单独的进程组id,但是这次我不给这个组提供终端控制。在运行时,给定背景命令的输出被输出到终端(在它完成执行之前),并且终端同时给用户返回提示符。应该发生的是,尝试写入终端的子进程应该得到一个SIGTTOU,并且应该停止,但这显然不会发生。我验证了分叉进程都具有相同的进程组id,并且这个id与shell的不同。
退出shell (通过ctrl)并返回到运行它的标准bash shell时,因为在shell终止时我没有收获后台进程,后台进程继续运行(这是例外)。奇怪的是,这个过程继续将输出写入bash,即使它不是前台进程。这导致我得出结论,要么由于POSIX错误(不太可能),这个后台进程没有得到任何SIGTTOU,要么它正在处理它们(导致停止被忽略的默认操作),或者后台进程忽略SIGTTOU。
在执行分叉进程之前,是否有一种方法可以确保它在接收到SIGTTOU时停止(假设exec二进制文件不会更改任何内容)?
发布于 2013-10-12 05:22:47
SIGTTOU被发送到后台进程,该进程只有在为终端设置termios标志TOSTOP时才试图写入该终端。默认情况下,它通常不设置,在这种情况下,后台进程可以愉快地写入终端。( TOSTOP标志不影响读取权限。如果进程试图读取,它将被发送一个SIGTTIN。)
所以,是的,前台进程可以做一些事情:使用tcsetattr设置TOSTOP
发布于 2013-10-12 05:50:23
解决方案是让分叉进程在调用exec之前执行以下操作:
struct termios term;
if (tcgetattr(STDIN_FILENO, &term) < 0)
printf("ERROR\n");
term.c_lflag = TOSTOP;
if (tcsetattr(STDIN_FILENO,TCSANOW,&term)<0)
printf("ERROR\n");https://stackoverflow.com/questions/19330488
复制相似问题