作业控制信号

POSIX.1 认为有以下 6 个与作业控制有关的信号。
* SIGCHLD:子进程已停止或终止。
* SIGCONT:如果进程已停止,则使其继续运行,否则忽略。
* SIGSTOP:停止信号(不能被捕捉或忽略)。
* SIGTSTP:交互式停止信号。
* SIGTTIN:后台进程组成员读控制终端。
* SIGTTOU:后台进程组成员写控制终端。
除 SIGCHLD 以外,大多数应用程序并不处理这些信号,交互式 shell 则通常会处理这些信号的所有工作。当键入挂起字符(通常是 Ctrl+Z)时,SIGTSTP 就被送至前台进程组的所有进程;当通知 shell 在前台或后台恢复运行一个作业时,shell 就向该作业中的所有进程发送 SIGCONT 信号。当对一个停止的进程产生一个 SIGCONT 信号时,该进程就继续,即使该信号是被阻塞或忽略的。
下面这个程序演示了当一个程序处理作业控制时通常所使用的规范代码序列。该程序只是将其标准输入复制到标准输出,而在信号处理程序中以注释形式给出了管理屏幕的程序(如 VI)所执行的典型操作。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

#define BUFFER 1024

static void sig_tstp(int signo){ // signal handler for SIGTSTP
/* ... move cursor to lower left corner, reset tty mode ... */

/* Unblock SIGTSTP, since it's blocked while we're handling it */
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGTSTP);
sigprocmask(SIG_UNBLOCK, &mask, NULL);

signal(SIGTSTP, SIG_DFL); // reset disposition to default
printf("send SIGTSTP\n");
kill(getpid(), SIGTSTP); // and send the signal to ourself
printf("received SIGCONT\n");

/* We won't return from the kill untill we're continued */

signal(SIGTSTP, sig_tstp); // reestablish signal handler

/* ... reset tty mode, redraw screen ... */
}

int main(void){
ssize_t n;
char buf[BUFFER];

/* Only catch SIGTSTP if we're running with a job-control shell */
if(signal(SIGTSTP, SIG_IGN) == SIG_DFL)
signal(SIGTSTP, sig_tstp);
while((n=read(STDIN_FILENO, buf, BUFFER)) > 0){
if(write(STDOUT_FILENO, buf, n) != n)
printf("write error\n");
}
if(n < 0)
printf("read error\n");
exit(0);
}

这里仅当 SIGTSTP 信号的配置是 SIG_DFL 时才安排捕捉该信号的理由是:init 会将 SIGTSTP、SIGTTIN 和 SIGTTOU 设置为 SIG_IGN,这种配置将被所有登录 shell 继承。所以当此程序由不支持作业控制的 shell(如 /bin/sh)启动时,此信号的配置将被设置为 SIG_IGN。只有作业控制 shell 才应将这 3 个信号重新设置为 SIG_DFL。
程序运行结果如下。

$ ./jobCtrlDemo.out
abcde # 读取输入
abcde # 输出
^Zsend SIGTSTP # Ctrl-Z 发送 SIGTSTP 信号挂起进程
[1]+ Stopped ./jobCtrlDemo.out
$ ps # 查看进程 ID
PID TTY TIME CMD
23893 pts/1 00:00:00 jobCtrlDemo.out
23914 pts/1 00:00:00 ps
82002 pts/1 00:00:05 bash
$
$ kill -SIGCONT 23893 # 发送 SIGCONT 信号使进程继续运行
received SIGCONT
[1]+ Stopped ./jobCtrlDemo.out

当键入挂起字符时,进程接到 SIGTSTP 信号,然后调用该信号处理程序。此时,应当进行与终端有关的处理(如将光标移到左下角、恢复终端工作方式等)。在将 SIGTSTP 重置为默认值(停止该进程),并解除了对此信号的阻塞(因为正在捕捉一个信号期间系统会自动地阻塞该信号)后,进程向自己发送同一信号 SIGTSTP,使系统停止该进程。仅当该进程接到 SIGCONT 信号后才会如同从 kill 函数返回一样继续运行。最后再将 SIGTSTP 重置为捕捉,并做一些终端处理工作(如重新绘制屏幕)。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值