曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5241|回复: 0
打印 上一主题 下一主题

信号处理

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2011-5-7 10:50:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
发送信号
Linux 编程中常见的几种信号:
信号

描述
1
SIGHUP
挂起进程
2
SIGINT
中断进程
3
SIGQUIT
停止进程
9
SIGKILL
无条件终止进程
15
SIGTERM
如果可能的话终止进程
17
SIGSTOP
无条件停止,但不终止进程
18
SIGTSTP
停止或暂停进程,但不终止它
19
SIGCONT
重新启动停止的进程

默认情况下,bash shell 会忽略它接收任何的 SIGQUIT 信号(有些版本的 bash shell 还会忽略 SIGTERM,但有些也不会屏蔽,当接收到 SIGTERM 时,进程会被终止且在终止后提示进程 Terminated .)。可以通过运行一个无限循环的脚本,然后通过 kill -s {信号} {PID} 来测试进程接收信号的情况。bash shell 会处理接收到的任何 SIGHUP 和 SIGINT 信号。如果 bash shell 收到一个 SIGHUP 信号,它会退出,在退出前,它将 SIGHUP 信号传递给 shell 启动的任意进程。在收到 SIGINT 信号时(Ctrl + C 组合键发出此信号),shell 会立即中断,内核停止向 shell 提供 CPU 处理时间,在此情况下,shell 将 SIGINT 信号传递给 shell 启动的任意进程以通知它们这种情况。

Ctrl + Z 组合键发出 SIGTSTP 信号,它停止运行中的进程,但不终止它,停止后的进程仍然驻留在内存中。这时可以通过 jobs 命令查看被停止的进程。
$ sh trap.sh
hello
hello
^Z           # Ctrl + Z 发出 SIGTSTP 信号
[1]+  Stopped                 sh trap.sh
使用 jobs 命令观察:
$ jobs
[1]+  Stopped                 sh trap.sh
在停止时使用 ps 命令观察进程情况:
$ ps au
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
... ... ... ...
beyes     3606  0.0  0.1   5024  1116 pts/0    T    10:41   0:00 sh trap.sh
... ... ... ...
上面,进程处于 T 状态,这表示它整被跟踪或者已经停止。
如果想结束这个停止的进程,则可以使用命令 kill -9 3606 。如果希望再次运行,简单的使用 fg 命令即可(这里只假设仅有一个停止的进程,如果有多个,可以 fg {睡眠进程编号} 唤醒) 。

捕获信号
捕获信号使用的是 trap 命令,它可以监控和拦截 Linux 信号。如果脚本收到 trap 列表中的信号,它将保护该信号不被 shell 处理,而是在本地处理它。下面是简单示例:
[Bash shell] 纯文本查看 复制代码
#!/bin/bash  

function crcl {
    echo "execute a function"
}

trap 'crcl;echo "It is ok"' SIGINT SIGTERM

count=1

while [ $count -le 5 ]
do
    echo "$count"
    sleep 10
    count=$[ $count + 1 ]
done
echo "End of the program"

上面只要捕获到 SIGINT 或 SIGTERM 信号,就会执行 trap 命令后面单引号里边的命令。在单引号里,可以执行多个命令,每个命令用分号隔开,当然也允许执行函数。

除了在脚本中捕获信号,还可以在脚本退出时捕获它们,这样就可以让 shell 完成作业时执行命令的快捷方式,方法是向 trap 添加 EXIT 信号:
trap '命令列表' EXIT
当脚本到达退出点时,就会触发 trap,shell 将执行 trap 命令列表中的命令,如果是提前退出脚本,那也能够捕获 EXIT 。

如果要移除捕获,那么使用破折号作为命令和想要恢复正常行为的信号列表。下面的代码对上面的稍作修改:
[Bash shell] 纯文本查看 复制代码
#!/bin/bash  

function crcl {
    echo "execute a function"
}

trap 'crcl;echo "It is ok"' SIGINT SIGTERM

count=1

while [ $count -le 10 ]
do
    echo "$count"
    sleep 10
    count=$[ $count + 1 ]
    if [ $count -eq 5 ]; then
        trap - SIGINT SIGTERM
    fi
done
echo "End of the program"

运行输出:
[beyes@SLinux shell]$ sh trap.sh
1
^Cexecute a function
It is ok
2
^Cexecute a function
It is ok
3
^Cexecute a function
It is ok
4
^Cexecute a function
It is ok
5
^C
从输出可以看到,当 count 变量值到达 5 时,解除了对 SIGINT 和 SIGTERM 信号的处理,那么当再次发出 SIGINT 信号时,脚本就直接退出了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-15 08:39 , Processed in 0.077369 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表