unix信号转载
来源:互联网 发布:淘宝如何修改店铺名称 编辑:程序博客网 时间:2024/06/01 23:27
引言
信号是软中断,很多比较重要的应用程序都需处理信号。
信号概念
每个信号都有一个名字,都以SIG开头,Linux和Solaris都支持自定义信号,信号定义在中。
信号发生时,可以告诉内核按照下列方式进行处理:
- 忽略该信号,两种信号不能忽略,SIGKILL和SIGSTOP
- 捕捉信号,调用信号处理函数,不能捕捉SIGKILL和SIGSTOP信号
- 按照系统默认的方式进行处理
signal函数
func是SIG_DEF, SIG_IGN或处理信号的函数地址
函数原型的意义:该函数返回一个函数指针,该指针接受一个int参数,而函数的参数为signo和一个函数指针,func为当信号signo到来时,执行的程序,返回之前执行的程序的指针。
查看头文件,则有以下声明:
在shell上面向进程发信号的指令,如SIGUSR1: kill -USR1 process_id
shell自动将后台进程对中断和退出设置为忽略。
进程创建时,子进程继承父进程的信号处理方式。
不可靠信号
早期的UNIX对信号的控制能力很差,一个信号发生了,但进程可能永远都不知道。早期UNIX对信号进行处理之后,将恢复信号的默认处理方式(假设用户设置了信号处理),为了避免系统恢复默认信号,则程序可以这样设计:
但是这样会产生一个窗口期,假如在进行信号处理到设置信号之间又产生该信号,而该信号被恢复为默认的方式,则不会产生预期的结果,这种问题还不会被察觉。
中断系统调用
早期UNIX的特性是:如果一个低速系统调用被信号中断,则它不会继续执行。该系统调用返回出错,errno置为EINTR。(低速系统调用是可以被永远阻塞的一种系统调用,读写磁盘I/O不属于低速系统调用)。
对于read、write系统调用,不同的系统会有两种不同的处理方式,一种是失败返回,errno置为EINTR;一种是成功返回,返回已接收到的部分数据量。与被中断的系统调用相关的问题是必须显示的处理系统调用:
只有低速的系统调用才会被信号中断,为了帮助程序使之不必处理系统中断,有些系统提供了中断系统调用的自动重启动,自动重启动的系统调用包括ioctl, read, write, readv, writev, wait 和 waitpid,前5个只有在低速的系统调用才会被中断,后两个遇到信号就会被中断。
可重入函数
进程捕捉到信号并对信号进行处理时,进程正常执行的指令序列就会被中断,转而进行信号处理,信号处理正常返回时(不调用exit或longjmp),会继续执行原先的指令序列;但是对某些中断会存在问题,比如进程正在执行malloc分配内存,而此时捕捉到一个系统调用,信号处理程序又调用malloc,这样可能会对程序造成破坏。
哪些函数是不可重入的:
- 已知它们使用静态数据结构
- 它们调用mallo或free
- 它们是标准I/O函数(printf等)
若在信号处理程序中调用一个不可重入的函数,则结果是不可以预见的。
可靠信号术语和语义
当进程对某个信号采取某种动作时,称向进程递送了一个信号,在信号的产生和递送的时间间隔内,称信号是未决的。
每个进程都有一个信号屏蔽字,它规定了要阻塞递送到该进程的信号集。对于每种可能的信号,该信号都有一位与之对应。若其对应已被设置,则它当前是被阻塞的。调用sigprocmask检测和更改当前信号屏蔽字,调用sigpending函数判定哪些信号是设置为阻塞并处于未决状态的。POSIX.1定义了一个信号集类型sigset_t,信号屏蔽字就存放在该信号集中。
alarm和pause函数
一个进程只能设置一个时钟,如果在调用alarm时上次设置的时钟还没有到达,则alarm返回上次余留秒数,并且alarm设置为新值。
如果当前设置的秒数为0,而且上次时钟没有到达,则取消当前设置的时钟,返回余留秒数。
只有执行了一个信号处理程序并返回时,pause才返回。
用alarm和pause实现sleep函数:
上面的程序会带来几个问题,其中最不易查觉的问题就是在一个繁忙的系统中,设置了alarm之后,没有等到pause的执行,闹钟就到了,则pause将会永远挂起,解决此问题的方法之一是使用longjmp函数。
下面用setmp和longjmp解决上面问题:
alarm不仅可以实现sleep,还可以设置低速系统调用的超时,如果低速系统调用超时,则用alarm中断该系统调用:
信号集
函数sigemptyset清除set中所有信号,sigfillset使set包括所有信号
sigprocmask函数
若oset非空,则进程当前信号屏蔽字通过oset返回,若set非空,则通过how设置信号屏蔽字。
how的说明:
how
说明
SIG_BLOCK
将信号屏蔽字设置为当前信号屏蔽字和set的并集
SIG_UNBLOCK
从当前信号屏蔽字排除set
SIG_SETMASK
被set指向的信号屏蔽字代替
如果sigprocmask释放了某个未决的信号,则该信号在sigprocmask返回之前将被调用。
sigpending函数
如果set非空,则set返回未决的信号集。
sigaction函数
sigaction函数的功能是检查或修改与指定信号相关联的处理动作,此函数取代了UNIX早期版本使用的signal函数
如果act非空,则要修改信号signo的动作,如果oact非空,则会返回该信号上一个动作
sa_mask是一个信号集,在调用信号捕捉函数之前,这一信号集要加到信号屏蔽字中。仅当信号处理函数返回时,进程的信号屏蔽字复位为原先值。在信号处理程序被调用时,操作系统建立的新信号屏蔽字包括正被递送的信号。
sa_flags字段指定对信号处理的各个选项,见P262表10-5
使用sigaction函数实现signal函数
不希望重启动由sigalrm中断的系统调用的原因是sigalrm可以设置低速系统调用的超时。
sigsetjmp和siglongjmp函数
信号处理程序中经常会调用longjmp函数以返回到程序的主循环中,而进入信号处理程序之前当前信号屏蔽字会屏蔽当前信号,再调用longjmp回到主程序时,信号屏蔽字会变成什么呢?POSIX没有说明setjmp和longjmp对信号屏蔽字的作用,而是定义了另外两个函数sigsetjmp和siglongjmp函数,sigsetjmp保存当前信号屏蔽字,当调用siglongjmp跳转到sigsetjmp执行的位置时,信号屏蔽字会恢复。
实例在sigjmp.c中实现。
sigsuspend函数
sigsuspend函数接受一个信号集指针,将信号屏蔽字设置为信号集中的值,在进程接受到一个信号之前,进程会挂起,当捕捉一个信号,首先执行信号处理程序,然后从sigsuspend返回,最后将信号屏蔽字恢复为调用sigsuspend之前的值。
sigsuspend的典型用法就是利用循环等待某一特定信号的到来,当进程捕捉到该信号,则进行特定的处理,例如给全局变量赋值等。
可用信号实现父子之间的进程同步,它们是TELL_WAIT,TELL_PARENT,WAIT_PARENT,TELL_CHILD,WAIT_CHILD,见程序sync_process.c。
- unix信号转载
- 【Unix】信号
- Unix 信号
- unix 信号
- 转载:UNIX系统中wait函数簇和SIGCLD信号的关系
- Unix信号说明
- UNIX信号机制浅析
- Unix信号处理
- UNIX信号学习
- Unix信号说明
- 信号概述(Unix && Linux)
- 有趣的UNIX信号
- UNIX的信号
- UNIX信号(下)
- Unix系统信号
- Unix信号列表
- Unix信号说明
- Unix信号集
- [leetcode] Search in Rotated Sorted Array II
- C++11新标准之三:nullptr
- 1229 数字游戏
- java基本数据类型初始值(默认值) ,在设计数据库时造成的问题
- sqlserver2008添加删除字段
- unix信号转载
- 译文:前端性能的重要性 The Importance of Frontend Performance
- MATLAB 信号分析FFT STFT
- Java关键字系列(class,package,import)
- mysql在一个表中存储创建时间和最近更新时间
- Sqlite sqlite3_config 报错 21
- 黑马程序员——Java基础——面向对象(2)继承
- 2014.09.04 周四-xml传变量-w3c:html
- 全局修改a链接的打开方式,javascript:void(0)会打开空白页面问题