Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1467734
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类: 系统运维

2012-05-14 15:15:25



工作控制是在1980年前后加入到BSD的一个特性。这个特性允许我们在单个终端开启多个工作(进程组),并控制哪些工作可以访问终端和哪些工作在后台运行。工作控制需要三种形式的支持:


1、一个支持工作控制的外壳;


2、内核里的终端驱动必须支持工作控制;


3、内核必须支持特定的工作控制信号。


SVR3提供了另一种形式的工作控制,被称为外壳层。BSD形式的工作控制,被POSIX.1选择,也是我们在这讨论的。在这个标准的更早的版本里,工作控制支持是可选的,但是现在POSIX.1要求平台来支持它。


从我们的角度,从一个外壳使用工作控制,我们可以在前台或后台开始一个工作。一个工作是简单的一个进程集合,经常是一个进程的管道。例如:vi main.c打开了一个由一个前台进程组成的工作。命令pr *.c | lpr &
make all &
在后台开启了两个工作。后台工作调用的所有进程都在后台里。


正 如我们说过的,为了使用工作控制提供的特性,我们需要使用支持工作控制的一个外壳。在早期系统,说出哪些外壳支持而哪些外壳不支持工作控制很简单。C外壳 支持工作控制、在Bourne外壳不支持、而在Korn外壳里是一个可选项,取决于主机是否支持工作控制。但是C外壳被移植到不支持工作控制的系统(例 如,系统V的早期版本),而SVR4 Bourne外壳,当使用名字jsh而不是sh时,会支持工作控制。Korn外壳继续支持工作控制,如果主机支持的话。Bourne-again外壳也支 持工作控制。我们将只泛泛地说一个支持工作控制,对应不支持工作控制的那些,当各种外壳的区别无关紧要时。


当我们开始一个后台工作进,外壳给它分配一个工作标识符并打印一个或多个进程ID。下面的脚本展示Korn外壳如何处理这个:
$make all > Make.out &
[1]         1475
$ pr *.c | lpr &
[2]         1490
$ (只输入回车)
[2] + Done
[1] + Done


make 的工作号为1而开始进程ID为1475.下一个管道的工作号为2而第一个进程的进程ID为1490。当工作完成时,而我们按下回车,外壳告诉我们工作完成 了。我们必须按回车的原因是让外壳打印它的提示。外壳不在任何随机时间打印后台工作的改变状态--只是在它打印它的提示前,来让我们输出一个新的命令行。 如果外壳不这样做,它可能在我们输入一个输入行时输出。


和终端驱动的交互由于一个特殊终端字符影响了前台工作而发生:挂起键(典型的Control-Z)。输出这个字符导致终端驱动发送SIGTSTP信号给前台进程组的所有进程。任何后台进程进程组不被影响。终端驱动查找三个特殊的字符,它们产生对前台进程组的信号:


1、中断字符(一般是DELETE或Control-C)产生SIGINT;


2、退出字符(一般是Control-backslash)产生SIGQUIE;


3、挂起字符(一般是Control-Z)产生SIGTSTP。


在18章,我们将看到我们怎样改变这三个字符成为我们选择的任意字符,以及我们如何禁止终端驱动处理这些特殊字符。


另 一个必须由终端驱动处理的工作控制可以发生。既然我们可以有一个前台工作和一个或多个后台工作,这些中的哪台接受我们在终端输入的字符呢?只有前台工作接 受终端输入。后台工作尝试从终端读不是一个错误,但是终端驱动察觉到它并向后台工作发送一个特殊的信号:SIGTTIN。这个信号一般停止后台工作。通过 使用外壳,我们收到这个通知并可以把这个工作带入前台,以便它可以从终端读取。证明如下:


$ cat > temp.foo &
[1] 2333
$ (回车)

[1]+  已停止               cat > temp.foo
$ fg %1
cat > temp.foo
hello, world
$ cat temp.foo
hello, world



外 壳在后台启动cat进程,但是当cat尝试读取它的标准输入(控制终端),终端驱动知道它是一个后台工作,发送SIGTTIN信号给这个后台工作。外壳察 觉它子进程状态的改变(回想8.6节wait和waitpid函数的讨论)并告诉我们工作已经被停止了。我们然后用外壳的fg命令把停止的工作移到前台 来。(参考shell的手册而来得到工作控制命令的所有细节,比如fg和bg,以及标识不同工作的各种方法。)这样做导致外壳把工作移到前台进程组 (tcsetpgrp)并发送继续信号(SIGCONT)给这个进程组。既然它现在在前台进程组时,这个工作可以从控制终端读取。


如果一个后台工作输出到控制终端会发生什么呢?这是一个我们可以允许或禁止的可选项。通常,我们使用stty命令来改变这个选项。(我们将在18章看到我们如何可以从一个程序里改变这个选项。)下面展示这如何工作:


$ cat temp.foo &
[1] 2385
$ hello, world
(输入回车)
[1]+  完成                  cat temp.foo
$ stty tostop
$ cat temp.foo &
[1] 2387
$ (输入回车)

[1]+  已停止               cat temp.foo
$ fg 1
cat temp.foo
hello, world


当我们禁止前台工作向控制终端写时,cat会在其尝试向标准输出写时阻塞,因为终端驱动标识了这个写是从一个后台进程来的,并向这个工作发送SIGTTOU信号。正如前面的例子,当我们使用外壳的fg命令把工作带入到前台时,工作完成。


下面总结了我们已经描述过的工作控制的一些特性:


1、init或inetd启动一个新的会话。这个会话包含后面的内容;


2、由init或inetd创建的getty或telnetd进程,在调用setsid后,建立控制终端,并通过exec执行login;
3、login通过exec执行登录外壳;


4、登录外壳调用setpgid创建前台进程组和后台进程组,并向终端驱动调用tcsetpgrp来为控制终端设置进程组;

5、终端上的用户与终端驱动交互,终端输入和终端产生的信号(SIGINT、SIGQUIT和SIGTSTP)被发送给前台进程;前台进程向终端驱动发送终端输出;

6、后台进程读取终端输入时,终端驱动向它发送SIGTTIN信号;后台进程向终端输出时,终端驱动可能向它发送SIGTTOU信号;


7、前台进程和后台进程的状态改变时,登录外壳会收到通知。


工 作控制是必需的还是可取的?工作控制最初在窗口终端被广泛使用前被设计和实现。一些人指出一个良好设计的窗口系统移除了工作控制的需求。一些人则抱怨工作 控制的实现--需要内核、终端驱动、外壳和一些应用程序的支持--是一个hack。一些人在一个窗口系统里使用工作控制,要求两者都需要。不管你的意见如 何,工作控制是POSIX.1的一个必需的特性。

阅读(371) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~