系统中断与SA_RESTART
今天在调试程序时,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 ) < )
return -; 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,readorwrite), 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_RESTARTflag 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() < ) /* 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其实是继续执行中断的函数,默认信号的处理函数是重复设置的。
系统中断与SA_RESTART的更多相关文章
- MCS-51系统中断优先级的软扩展
摘要:鉴于MCS-51系统只提供“二级中断嵌套”,提出扩展51系统中断优先级的纯软件方法.其利用51系统内建的中断允许寄存器IE和中断优先级寄存器IP,通过屏蔽字机制来实现:以C51的形式,给出这种扩 ...
- 很多win10系统用户都遇见了开机发现任务管理器中有个系统中断进程占用cpu99%的问题,
很多win10系统用户都遇见了开机发现任务管理器中有个系统中断进程占用cpu99%的问题,尝试了网上提供的方法都不能得到有效的解决.下面小编就为大家详细的介绍电脑工程师提供的正确的解决姿势. 出现系统 ...
- Nucleus 实时操作系统中断(下)
Nucleus 实时操作系统中断(下) Nucleus RTOS兼容性 由于中断在Nucleus SE中的实现方式与Nucleus rto截然不同,因此不应期望有特定的兼容性.Nucleus RTOS ...
- Nucleus 实时操作系统中断(上)
Nucleus 实时操作系统中断(上) Interrupts in the Nucleus SE RTOS 所有现代微处理器和微控制器都有某种中断设施.这种能力对于提供许多应用程序所需的响应能力是必不 ...
- 痞子衡嵌入式:嵌入式Cortex-M系统中断延迟及其测量方法简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是Cortex-M系统中断延迟及其测量方法. 在嵌入式领域里,实时性是个经常被我们挂在嘴边的概念,这里的实时性主要强调得是当外界事件发生时 ...
- 痞子衡嵌入式:利用GPIO模块来测量i.MXRT1xxx的系统中断延迟时间
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx的系统中断延迟时间. 在 <Cortex-M系统中断延迟及其测量方法简介> 一文里,痞子衡介绍了 Cor ...
- epoll_wait会被系统中断唤醒
今天,当一个程序在epoll_wait阻塞时,用strace跟踪了一下,结果epoll_wait就被EINTR唤醒了,并且返回-1: 所以,当epoll_wait返回-1时,需要判断errno是不是E ...
- Linux内核分析-系统中断在内核中的实现
分析system_call中断处理过程 在MenuOS中添加上周所运用到的系统调用 即在Linuxkernel/menu/test.c文件中,添加代码如下: int Mkdir() { const c ...
- IDT系统中断描述表以及绕过Xurtr检测的HOOK姿势
什么是中断? 指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程.即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个 ...
随机推荐
- Python源码学习之初始化(三)-PyDictObject的初始化
先来看它的定义 typedef struct _dictobject PyDictObject; struct _dictobject { PyObject_HEAD Py_ssize_t ma_fi ...
- python查看删除你微信的账号
#应用环境:python2.7 #!/usr/bin/env python # coding=utf-8 from __future__ import print_function import os ...
- linux服务器加入windows域时报错Ticket expired
[root@rusky]# net ads join -U administrator Enter administrator's password: kinit succeeded but ads_ ...
- [jQuery] 使用jQuery printPage plugin打印其他頁面內容
目標: 點選按鈕後可以打印其他頁面的內容,可用於套版.內部表單套印...等等. 程式碼: 1.View(HTML布局) <h2>維修申請單</h2> <form id=& ...
- c# 根据窗口截图,合并图片
c# 根据窗口截图,合并图片 public class CaptureWindows { #region 类 /// <summary> /// Helper class containi ...
- 初识数据字典【weber出品必属精品】
数据字典结构 有两部分组成: 1. 基表:以$结尾的系统表,在创建数据库的时候,oracle自动创建的表 2. 用户可以访问的视图 数据字典的种类 DICTIONARY:简称DICT,所有的数据字典, ...
- xcode中折叠打开代码
- jdbc oracle 连接字符串
1.普通SID方式 jdbc:oracle:thin:username/password@x.x.x.1:1521:SID 2.普通ServerName方式 jdbc:Oracle:thin:user ...
- java内部类实现多继承
class Example1 { public String name() { return "liutao"; } } class Example2 { public int a ...
- poj2385 简单DP
J - 简单dp Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:65536KB 64bit ...