本篇需要理清后台进程组与控制终端的关系。我们已经知道,如果会话有一个控制终端,只有前台作业接收终端输入。

1. 问题提出

如果后台进程组中的进程尝试读写控制终端,会怎么样?这里有两种情况,分别如下:

  • 读控制终端

终端驱动程序会检测到此种情况,并向后台进程组中的所有进程发送一个特定信号 SIGTTIN. 默认情况下些信号导致此后台进程组停止。

  • 写控制终端

终端驱动程序会检测到并向后台进程组中的所有进程发送信号 SIGTTOU.

2. 实验

实验中编写程序 bg.c,捕获 SIGTTIN 和 SIGTTOU.

  • 代码
// bg.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void handler(int sig) {
if (sig == SIGTTIN) {
printf("hello SIGTTIN\n");
}
if (sig == SIGTTOU) {
printf("hello SIGTTOU\n");
exit(0);
}
}

int main(int argc, char* argv[]) {
int len;
char buf[64];

struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;

if (sigaction(SIGTTIN, &act, NULL) < 0) {
perror("signal SIGTTIN");
}
if (sigaction(SIGTTOU, &act, NULL) < 0) {
perror("signal SIGTTOU");
}

while(1) {
len = read(STDIN_FILENO, buf, 64);
if (len > 0) {
write(STDOUT_FILENO, buf, len);
}
else {
perror("read");
}
}
return 0;
}
  • 编译和运行
$ gcc bg.c -o bg
$ ./bg &

注: ​​&​​ 表示将该进程组设置为后台进程组。

  • 运行结果

71-后台进程组与控制终端_信号

图1 后台进程组中的进程读写控制终端

3. 总结

  • 理解后台进程组中的进程读写控制终端的后果