Chinaunix首页 | 论坛 | 博客
  • 博客访问: 631006
  • 博文数量: 244
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-27 09:53
个人简介

记录学习,记录成长

文章分类

全部博文(244)

我的朋友

分类: LINUX

2015-07-23 19:26:05

1.信号的概念:
        软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。  
        收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:1.是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处 理。2.忽略某个信号,对该信号不做任何处理,就象未发生过一样。3.对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信 号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。 
    在进程表的表项中有一个软中断信号域,该域中每一位对应一个信号,当有信号发送给进程时,对应位置位。由此可以看出,进程对不同的信号可以同时保留,但对于同一个信号,进程并不知道在处理之前来过多少个
2.信号的类型
可通过kill  -l来列出系统中的所有信号类型
[root@localhost shell]# kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
信号介绍:
1) SIGHUP :在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联.   
2) SIGINT :程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出   
3) SIGQUIT :和SIGINT类似, 但由QUIT字符(通常是Ctrl-/)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号.   
4) SIGILL :执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号.   
5) SIGTRAP :由断点指令或其它trap指令产生. 由debugger使用.   
6) SIGABRT :程序自己发现错误并调用abort时产生.   
7) SIGIOT :在PDP-11上由iot指令产生, 在其它机器上和SIGABRT一样.   
8) SIGBUS :非法地址, 包括内存地址对齐(alignment)出错. eg: 访问一个四个字长的整数, 但其地址不是4的倍数.   
9) SIGFPE :在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误.   
10) SIGKILL:用来立即结束程序的运行. 本信号不能被阻塞, 处理和忽略.   
11) SIGUSR1 :留给用户使用   
12) SIGSEGV :试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据.   
13) SIGUSR2 :留给用户使用   
14) SIGPIPE :Broken pipe   
15) SIGALRM :时钟定时信号, 计算的是实际的时间或时钟时间. alarm函数使用该信号.   
16) SIGTERM :程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理. 通常用来要求程序自己正常退出. shell命令kill缺省产生这个信号.   
17) SIGCHLD :子进程结束时, 父进程会收到这个信号.   
18) SIGCONT :让一个停止(stopped)的进程继续执行. 本信号不能被阻塞. 可以用一个handler来让程序在由stopped状态变为继续执行时完成特定的工作. 例如, 重新显示提示符   
19) SIGSTOP :停止(stopped)进程的执行. 注意它和terminate以及interrupt的区别: 该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略.   
20) SIGTSTP :停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号   
21) SIGTTIN :当后台作业要从用户终端读数据时, 该作业中的所有进程会收到SIGTTIN信号. 缺省时这些进程会停止执行.   
22) SIGTTOU :类似于SIGTTIN, 但在写终端(或修改终端模式)时收到.   
23) SIGURG :有紧急数据或out-of-band数据到达socket时产生.   
24) SIGXCPU :超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/改变   
25) SIGXFSZ :超过文件大小资源限制.   
26) SIGVTALRM :虚拟时钟信号. 类似于SIGALRM, 但是计算的是该进程占用的CPU时间.   
27) SIGPROF :类似于SIGALRM/SIGVTALRM, 但包括该进程用的CPU时间以及系统调用的时间.   
28) SIGWINCH :窗口大小改变时发出.   
29) SIGIO :文件描述符准备就绪, 可以开始进行输入/输出操作.   
30) SIGPWR :Power failure
同一个信号在不同的系统中值可能不一样,所以建议最好使用为信号定义的名字,而不要直接使用信号的值


3.下面说一下trap命令
trap是一个shell内建命令,它用来在脚本中指定信号如何处。比如,按Ctrl+C会使脚本终止执行,实际上系统发送了SIGINT信号给脚本进程,SIGINT信号的默认处理方式就是退出程序。如果要在Ctrl+C不退出程序,那么就得使用trap命令来指定一下SIGINT的处理方式了。trap命令不仅仅处理Linux信号,还能对脚本退出(EXIT)、调试(DEBUG)、错误(ERR)、返回(RETURN)等情况指定处理方式。

trap命令的参数分为两部分,前一部分是接收到指定信号时将要采取的行动,后一部分是要处理的信号名
如果要重置某个信号的处理条件到其默认值,只需简单的将command设置为-。如果要忽略某个信号,就把command设置为空字符串‘’。一个不带参数的trap命令将列出当前设置的信号及其行动的清单

常用参数:

⑴格式:trap     "commands"     signals或trap     'commands'    signals

当shell接收到signals指定的信号时,执行commands命令。

⑵格式:trap     signals
如果没有指定命令部分,那么就将信号处理复原。比如 trap INT 就表明恢复Ctrl+C退出

⑶格式:trap     ""     signals
忽略信号signals,可以多个,比如 trap "" INT 表明忽略SIGINT信号,按Ctrl+C也不能使脚本退出。又如 trap "" HUP 表明忽略SIGHUP信号,即网络断开时也不能使脚本退出。

⑷格式:trap -p signal

把当前的trap设置打印出来。

⑸格式:trap "commands" EXIT

脚本退出时执行commands指定的命令。

⑹格式:trap "commands" DEBUG

在脚本执行时打印调试信息,比如打印将要执行的命令及参数列表

⑺格式:trap "commands" ERR

当命令出错,退出码非0,执行commands指定的命令

格式:trap "commands" RETURN

当从shell函数返回、或者使用source命令执行另一个脚本文件时,执行commands指定的命令

如:
[root@localhost shell]# trap -p
[root@localhost shell]# trap "echo redhat" INT    或者[root@localhost shell]# trap 'echo "hello" ' INT
[root@localhost shell]# trap -p
trap -- 'echo redhat' SIGINT
[root@localhost shell]# trap -p INT
trap -- 'echo redhat' SIGINT
[root@localhost shell]# ^Credhat        #这里按下了Ctrl+c组合键

[root@localhost shell]# trap - INT
[root@localhost shell]# trap -p INT
[root@localhost shell]# 


4.trap在shell脚本中的使用
4.1代码:
[root@localhost shell]# cat signal_catch.sh 
#!/bin/bash
#
net=122.207.210
for i in {1..15}
do
   if ping -c 1 -W 1 $net.$i &> /dev/null
   then
        echo "$net.$i is up....."
   else
        echo "$net.$i is down..."
   fi
done
结果:
[root@localhost shell]# ./signal_catch.sh 
122.207.210.1 is down...
122.207.210.2 is down...
^C122.207.210.3 is down...
122.207.210.4 is down...
^C122.207.210.5 is down...
122.207.210.6 is down...
执行时,我按下了Ctrl+c组合键,但是并没有终止程序,这是因为Ctrl+c这个信号被ping命令捕捉接收到了而没有被该脚本接收,所以Ctrl+c一下只是此时的ping命令不执行了,而脚本还是会继续执行;
那么如何让脚本捕捉到信号并终止呢——在脚本中写一个信号捕捉的命令即可
4.2代码:
[root@localhost shell]# cat signal_catch.sh 
#!/bin/bash
#
net=122.207.210
trap ' echo "quit..." && exit 1' INT        #这里的&&也可以换为;号来执行多个命令,但是必须在' '号内,如果在外面那脚本就直接退出了
for i in {1..15}
do
   if ping -c 1 -W 1 $net.$i &> /dev/null     
   then
        echo "$net.$i is up....."
   else
        echo "$net.$i is down..."
   fi
done
结果:
[root@localhost shell]# ./signal_catch.sh 
122.207.210.1 is down...
122.207.210.2 is down...
122.207.210.3 is down...
122.207.210.4 is down...
122.207.210.5 is down...
^Cquit...
当你Ctrl+C时脚本就会收到INT信号,输出quit并退出脚本
如果捕捉到信号时要执行的命令很多时,为了使脚本简洁管理方便,可以将所有要执行的命令写入一个函数中,然后trap  '函数名'  信号列表
如:
4.3代码:
[root@localhost shell]# cat signal_catch.sh 
#!/bin/bash
#
net=122.207.210
clear() {
        echo "many commands...."
        date
        exit 1
}
trap 'clear' INT
for i in {1..15}
do
   if ping -c 1 -W 1 $net.$i &> /dev/null
   then
        echo "$net.$i is up....."
   else
        echo "$net.$i is down..."
   fi
done
结果:
[root@localhost shell]# ./signal_catch.sh 
122.207.210.1 is down...
122.207.210.2 is down...
^Cmany commands....
Thu Jul 23 04:21:23 PDT 2015


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