linux信号量 signal

原文地址:http://blog.csdn.net/c453787298/article/details/23844017

一 信号量

1、基本概念 


软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。

收 到信号的进程对各种信号有不同的处理方法。

处理方法可以分为三类:

第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处 理。第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信 号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。 


在进程表的表项中有一个软中断信号域,该域中每一位对应一个信号,当有信号发送给进程时,对应位置位。由此可以看出,进程对不同的信号可以同时保留,但对于同一个信号,进程并不知道在处理之前来过多少个。 


2、信号的类型 


发出信号的原因很多,这里按发出信号的原因简单分类,以了解各种信号: 


(1) 与进程终止相关的信号。当进程退出,或者子进程终止时,发出这类信号。 

(2) 与进程例外事件相关的信号。如进程越界,或企图写一个只读的内存区域(如程序正文区),或执行一个特权指令及其他各种硬件错误。 

(3) 与在系统调用期间遇到不可恢复条件相关的信号。如执行系统调用exec时,原有资源已经释放,而目前系统资源又已经耗尽。 

(4) 与执行系统调用时遇到非预测错误条件相关的信号。如执行一个并不存在的系统调用。 

(5) 在用户态下的进程发出的信号。如进程调用系统调用kill向其他进程发送信号。 

(6) 与终端交互相关的信号。如用户关闭一个终端,或按下break键等情况。 

(7) 跟踪进程执行的信号。 

Linux支持的信号列表如下。很多信号是与机器的体系结构相关的,首先列出的是POSIX.1中列出的信号: 


信号 值 处理动作 发出信号的原因 

---------------------------------------------------------------------- 

SIGHUP 1 A 终端挂起或者控制进程终止 

SIGINT 2 A 键盘中断(如break键被按下) 

SIGQUIT 3 C 键盘的退出键被按下 

SIGILL 4 C 非法指令 

SIGABRT 6 C 由abort(3)发出的退出指令 

SIGFPE 8 C 浮点异常 

SIGKILL 9 AEF Kill信号 

SIGSEGV 11 C 无效的内存引用 

SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道 

SIGALRM 14 A 由alarm(2)发出的信号 

SIGTERM 15 A 终止信号 

SIGUSR1 30,10,16 A 用户自定义信号1 

SIGUSR2 31,12,17 A 用户自定义信号2 

SIGCHLD 20,17,18 B 子进程结束信号 

SIGCONT 19,18,25 进程继续(曾被停止的进程) 

SIGSTOP 17,19,23 DEF 终止进程 

SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键 

SIGTTIN 21,21,26 D 后台进程企图从控制终端读 

SIGTTOU 22,22,27 D 后台进程企图从控制终端写 


下面的信号没在POSIX.1中列出,而在SUSv2列出 


信号 值 处理动作 发出信号的原因 

-------------------------------------------------------------------- 

SIGBUS 10,7,10 C 总线错误(错误的内存访问) 

SIGPOLL A Sys V定义的Pollable事件,与SIGIO同义 

SIGPROF 27,27,29 A Profiling定时器到 

SIGSYS 12,-,12 C 无效的系统调用 (SVID) 

SIGTRAP 5 C 跟踪/断点捕获 

SIGURG 16,23,21 B Socket出现紧急条件(4.2 BSD) 

SIGVTALRM 26,26,28 A 实际时间报警时钟信号(4.2 BSD) 

SIGXCPU 24,24,30 C 超出设定的CPU时间限制(4.2 BSD) 

SIGXFSZ 25,25,31 C 超出设定的文件大小限制(4.2 BSD) 

(在这里,- 表示信号没有实现;有三个值给出的含义为,第一个值通常在Alpha和Sparc上有效,中间的值对应i386和ppc以及sh,最后一个值对应mips。信号29在Alpha上为SIGINFO / SIGPWR ,在Sparc上为SIGLOST。) 


处理动作一项中的字母含义如下 

A 缺省的动作是终止进程 

B 缺省的动作是忽略此信号 

C 缺省的动作是终止进程并进行内核映像转储(dump core) 

D 缺省的动作是停止进程 

E 信号不能被捕获 

F 信号不能被忽略 


二 信号机制


1、内核对信号的基本处理方法 


内 核给一个进程发送软中断信号的方法,是在进程所在的进程表项的信号域设置对应于该信号的位。这里要补充的是,如果信号发送给一个正在睡眠的进程,那么要看 该进程进入睡眠的优先级,如果进程睡眠在可被中断的优先级上,则唤醒进程;否则仅设置进程表中信号域相应的位,而不唤醒进程。这一点比较重要,因为进程检 查是否收到信号的时机是:一个进程在即将从内核态返回到用户态时;或者,在一个进程要进入或离开一个适当的低调度优先级睡眠状态时。 

内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时。所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。 

处理方法可以分为三类:

第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处 理。第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信 号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。 


三、有关信号的系统调用

1、signal 系统调用 

系统调用signal用来设定某个信号的处理方法。该调用声明的格式如下: 

void (*signal(int signum, void (*handler)(int)))(int); 

在使用该调用的进程中加入以下头文件: 

#include <signal.h>


#include <signal.h> 
#include <unistd.h> 
#include <stdio.h> 
void sigroutine(int dunno) { /* 信号处理例程,其中dunno将会得到信号的值 */ 
switch (dunno) { 
case 1: 
printf("Get a signal -- SIGHUP "); 
break; 
case 2: 
printf("Get a signal -- SIGINT "); 
break; 
case 3: 
printf("Get a signal -- SIGQUIT "); 
break; 
} 
return; 
} 

int main() { 
printf("process id is %d ",getpid()); 
signal(SIGHUP, sigroutine); //* 下面设置三个信号的处理方法 
signal(SIGINT, sigroutine); 
signal(SIGQUIT, sigroutine); 
for (;;) ; 
} 

其中信号SIGINT由按下Ctrl-C发出,信号SIGQUIT由按下Ctrl-发出。该程序执行的结果如下: 

localhost:~$ ./sig_test 
process id is 463 
Get a signal -SIGINT //按下Ctrl-C得到的结果 
Get a signal -SIGQUIT //按下Ctrl-得到的结果 
//按下Ctrl-z将进程置于后台 
[1]+ Stopped ./sig_test 
localhost:~$ bg 
[1]+ ./sig_test & 
localhost:~$ kill -HUP 463 //向进程发送SIGHUP信号 
localhost:~$ Get a signal – SIGHUP 
kill -9 463 //向进程发送SIGKILL信号,终止进程 
localhost:~$ 



2、kill 系统调用 


系统调用kill用来向进程发送一个信号。该调用声明的格式如下: 

int kill(pid_t pid, int sig); 

在使用该调用的进程中加入以下头文件: 

#include <sys/types.h> 

#include <signal.h>


3、pause系统调用 


系统调用pause的作用是等待一个信号。该调用的声明格式如下: 

int pause(void); 

在使用该调用的进程中加入以下头文件: 

#include <unistd.h> 


#include <unistd.h> 
#include <stdio.h> 
#include <signal.h> 
void sigroutine(int unused) { 
printf("Catch a signal SIGINT "); 
} 

int main() { 
signal(SIGINT, sigroutine); 
pause(); 
printf("receive a signal "); 
} 

在这个例子中,程序开始执行,就象进入了死循环一样,这是因为进程正在等待信号,当我们按下Ctrl-C时,信号被捕捉,并且使得pause退出等待状态。



4、alarm和 setitimer系统调用 








  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值