作业控制,它允许在一个终端上启动多个作业(进程组),它控制哪一个作业可以访问该终端,以及哪些作业在后台运行。作业控制要求下面三种形式的支持:
(1)支持作业控制的shell。
(2)内核中的终端驱动程序必须支持作业控制。
(3)内核必须提供对某些作业控制信号的支持。
从shell使用作业控制功能角度讲,用户可以在前台或后台启动一个作业。一个作业只是几个进程的集合,通常是一个进程的管道线。例如:
vi main.c
在前台启动了只有一个进程组成的一个作业。命令:
pr *.c | lpr &
make all &
在后台启动了两个作业。这两个后台作业调用的所有进程都在后台运行。
当启动一个后台作业时,shell赋予它一个作业标识,并打印一个或几个进程ID。
我们可以键入一个影响前台作业的特殊字符——挂起键(一般采用Ctrl+Z)与终端驱动程序进行交互。键入此字符使终端驱动程序将信号SIGTSTP送至前台进程组中的所有进程,后台进程组作业则不受影响。实际上有下面三个特殊字符可使终端驱动程序产生信号,并将它们送至前台进程组:
中断字符(一般采用DELETE或Ctrl+C)产生SIGINT。
退出字符(一般采用Ctrl+\)产生SIGQUIT。
挂起字符(一般采用Ctrl+Z)产生SIGTSTP。
终端驱动程序必须处理与作业控制有关的另一种情况。我们可以有一个前台作业和若干个后台作业,这些作业中哪一个接受我们在终端上键入的字符呢?只有前台作业接收终端输入。如果后台作业试图读终端,那么这并不是一个错误,但是终端驱动程序将检测这种情况,并且向后台作业发送一个特定的信号SIGTTIN。该信号通常会暂时停止此后台作业,而shell则向有关用户发出这种情况的通知,然后用户就可以用shell命令将此作业转为前台作业运行,于是它就可以读终端。
如果后台作业输出到控制终端又将发生什么呢?这是一个我们可以允许或禁止的选项。通常,可以用stty(1)命令改变这一选项。在用户禁止后台作业写到控制终端时(使用命令stty tostop(关于stty命令用法:http://micalli.blog.51cto.com/509064/640729)),如果后台作业输出到控制终端,终端驱动程序将该写操作标识为来自于后台进程,并向该作业发送SIGTTOU信号。
终端I/O和终端产生的信号总是从前台进程组连接到实际终端。
进程属于一个进程组,而进程组属于一个会话。会话可能有也可能没有控制终端。如果它确实有一个控制终端,则此终端设备知道其前台进程的进程组ID。这个值可以用tcsetpgrp函数在终端驱动程序中设置。前台进程组ID是终端的一个属性,而不是进程的属性。
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。