任务控制

任务控制

任务控制这个功能允许我们从单独的终端里开始多个任务(进程组)并去控制这些任务访问终端并在后台返回任务的结果。任务控制需要三种支持形式:

  1. 一个支持任务控制的shell
  2. 终端驱动必须支持任务控制
  3. 内核必须支持某些任务控制的信号

SHELL并不会打印出后台任务状态改变的信息,只有在需要输入新的命令行时,才会打印出提示。

在和终端驱动交互时,一些特殊字符会影响前台任务:如挂起键(ctrl+z)。这个字符会让终端驱动发送SIGTSTP信号到前台进程组中所有的进程。所有后台进程组中的任务不会受到影响。终端驱动可以识别出三种特殊字符,它产生的信号会发送到前台进程组中。

  • 中断字符(一般是DELETE或ctrl+c)产生SIGINT
  • 退出字符(一般是CTRL+\)产生SIGQUIT
  • 挂起字符(一般是CTRL+Z)产生SIGTSTP

只要能被终端驱动处理,也可以产生其它的控制条件。只有前台任务可以收到终端输入。当终端驱动发现后台任务尝试从终端读取时,它会发送一个特殊信号给后台任务:SIGTTIN。这个信号一般是停止后台任务;通过使用SHELL,我们会得到一个通知,并能让该任务回到前台,如:

   $ cat > temp.foo &          start in background, but it'll read from standard input
   [1]     1681
   $                           we press RETURN
   [1] + Stopped (SIGTTIN)     cat > temp.foo &
   $ fg %1                     bring job number 1 into the foreground
   cat > temp.foo              the shell tells us which job is now in the foreground
   
   hello, world                enter one line
   
   ^D                          type the end-of-file character
   $ cat temp.foo              check that the one line was put into the file
   hello, world

shell在后台开始cat进程,但是当cat尝试读取它的标准输入(当前控制终端)时,终端驱动知道它是一个后台任务,发送SIGTTIN信号到后台任务。shell发现子进程状态改变,并告诉我们这个任务已经停止。之后,我们用fg命令把停止的任务移动到前台。这么做使得shell把任务放到前台进程组(tcsetpgrp),并发送继续信号(SIGCONT)到进程组。因为该任务已经在前台进程组中,所以它能从控制终端中读取。

后台任务发送数据到控制终端时会发生什么?这是个选项,我们可以允许也可以禁止。一般我们用stty命令改变这个选项。下面显示了它是如何工作的:

   $ cat temp.foo &             execute in background
   [1]     1719
   $ hello, world               the output from the background job appears after the prompt
                                we press RETURN
   [1] + Done              cat temp.foo &
   $ stty tostop                disable ability of background jobs to output to
 controlling terminal
   $ cat temp.foo &             try it again in the background
   [1]     1721
   $                            we press RETURN and find the job is stopped
   [1] + Stopped(SIGTTOU)               cat temp.foo &
   $ fg %1                      resume stopped job in the foreground
   cat temp.foo                 the shell tells us which job is now in the foreground
   hello, world                 and here is its output

当我们禁止后台任务向控制终端输出时,cat将会阻塞它输出到标准输出,因为终端驱动标识了这个动作来自后台进程,并向任务发送SIGTTOU信号。就像之前的例子一样,使用fg命令把任务带到前台,之后任务完成所有任务。

图9.8汇总了任务控制的一些功能。在终端驱动块中的实线意味着终端I/O(terminal I/O)和终端产生的信号(terminal-generated signals)一直从着前台进程组连接到实际终端。而虚线连接的SIGTTOU信号意味着一个后台进程输到终端的输出是可选的。

figure9-8

Comments are closed.