系统中断与SA_RESTART
来源:互联网 发布:网络研修的收获 编辑:程序博客网 时间:2024/05/21 21:47
今天在调试程序时,sem_timedwait居然返回了一个Interrupted system call,错误码为EINTR。系统中断这东西我一向只闻其名,不见其"人",不想今天遇上了,脑中一片空白,赶紧上网恶补一下。
系统中断,要从慢系统调用(slow system call)说起,请参考 http://blog.csdn.net/benkaoya/article/details/17262053 。慢系统调用就是会阻塞的函数调用,一般是IO调用或有锁的函数。如read,sem_timedwait,这些函数可以会阻塞当前进程一段时间,所以"慢"。在阻塞的这段时间里,进程可能会收到内核的一些信号,这些信号优先级高,需要优先处理的,不能等这些调用完成后才处理信号。于是系统先去处理信号,然后强制这些函数以出错的形式返回,其错误码(errno)就是EINTR。这整个过程就是系统中断。
程序长时间运行,可能会遇到系统中断,如调试时会触发SIGTRAP,子进程当掉会遇到SIGCHLD...这些信号,有可能是正常的,或者不影响程序的运行。如果捕捉到错误就粗暴地将进程关闭,可能造成不必要的损失。因此,在这些慢调用的地方,需要检测错误是否为EINTR。如:
int wait(){struct timespec ts;if ( clock_gettime( CLOCK_REALTIME,&ts ) < 0 )return -1;ts.tv_sec += sec;ts.tv_nsec += nano_sec;ts.tv_sec += ts.tv_nsec/NSECTOSEC;ts.tv_nsec = ts.tv_nsec%NSECTOSEC;int ret = sem_timedwait( m_psem,&ts );if ( EINTR == ret )ret = wait();/* 遇到系统中断,再等一次 */return ret;}
这是老的处理方法(signal函数),在新的信号处理函数sigaction中可以指定收到某个信号时是否可以自动恢复函数执行(即在处理完消息后,继续执行原来中断的函数,像什么也没发生一样)。参考http://www.gnu.org/software/libc/manual/html_node/Flags-for-Sigaction.html,设置flag为SA_RESTART,表示继续原来的函数。
- Macro: int SA_RESTART
This flag controls what happens when a signal is delivered during certain primitives (such as
open
,read
orwrite
), and the signal handler returns normally. There are two alternatives: the library function can resume, or it can return failure with error codeEINTR
.The choice is controlled by the
SA_RESTART
flag for the particular kind of signal that was delivered. If the flag is set, returning from a handler resumes the library function. If the flag is clear, returning from a handler makes the function fail. See Interrupted Primitives .
在http://www.gnu.org/software/libc/manual/html_node/Interrupted-Primitives.html#Interrupted-Primitives中,说明了处理了系统中断的三种处理方法。
- 自己检测EINTR并手动重新调用自己的代码
- 使用TEMP_FAILURE_RETRY,在表达式返回EINTR并自动调用表达式,就是第一种方法的封装。
- sigaction中指定SA_RESTART
在处理系统中断时,会中断当前代码,去执行信息处理函数,然后继续执行当前代码。这相当于一种异步调用,需要考虑函数是否可重入。比如:
char *p = new char[DEFAULT_LEN];void sig_handler(int signum){delete []p;p = NULL;}void read(){if ( NULL == p )return;if ( wait() < 0 ) /* wait 函数见上面 */return;read( fd,p,DEFAULT_LEN );}
在这段代码中,read函数看似安全,因为已经检测了p指针。但是,如果在wait的时候触发了信号,调用了sig_handler,处理完sig_handler后继续执行read函数,会操作空指针。还有一些系统函数也是需要检测可重入的。见http://www.ibm.com/developerworks/cn/linux/l-reent.html#resources
PS:之前一直没接触过系统中断,这次收获不少。学习信号时,一直以为SA_RESTART是各 和SA_RESETHAND 相对应的。一个重复设置信号的处理函数,一个是只设置一次信号的处理函数,然后设置信号的处理函数为默认。没想到SA_RESTART其实是继续执行中断的函数,默认信号的处理函数是重复设置的。
转载:http://www.cnblogs.com/coding-my-life/p/4264462.html?utm_source=tuicool&utm_medium=referral
- 系统中断与SA_RESTART
- 关于被中断的系统调用,看SA_RESTART标志的作用
- 中断与中断系统
- 定时与中断系统
- 系统调用与中断
- sigaction,SA_RESTART
- linux 中断与系统调用
- linux中断与系统调用
- 中断、异常与系统调用
- 存储、中断、总线、与I/O系统_____中断系统
- ARM7/9 的中断与 RTOS 系统
- 慢系统调用与信号中断
- 信号中断 与 慢系统调用
- 信号中断 与 慢系统调用
- 信号中断 与 慢系统调用
- ARM7/9 的中断与 RTOS 系统
- 慢系统调用与信号中断(转)
- 信号中断 与 慢系统调用
- OpenCv-python之图像的缩放和旋转
- easyUi中portal组件的使用
- MyAppliction
- C#开发微信公众平台-就这么简单(附Demo)
- JAVA中final关键字
- 系统中断与SA_RESTART
- POJ 3723-Constription [最大权森林] 《挑战程序设计竞赛》2.5
- jquery3.2 在线引用地址
- L1-006. 连续因子
- asp.net 小技巧
- MyPageAdapter
- 【Hibernate】(三)持久化对象的生命周期
- 深入分析java线程池的实现原理
- Java基础之Math类