中断的系统调用 -- 系统调用的重新启动和可重入函数

2014-08-20 13:23:52   最后更新: 2014-08-20 13:23:52   访问数量:702




信号发生的时刻,内核会中断正在执行的指令序列,跳转到信号处理函数中执行

信号处理函数中如果没有使用exit或longjmp,当函数执行后会跳回捕捉到信号时正在执行的正常指令序列中,类似于硬件中断的处理方式

但是被中断的系统调用并不一定是可以完全恢复的,比如对低速设备进行操作的时候被中断,因此在unix中引入了自动重启机制

会被自动重启的系统调用有:ioctl、read、readv、write、writev、wait、waitpid

因为应用程序并不是总是希望去重新启动这些系统调用,所以在不同的系统中的处理是不同的

在进程中,如果正在执行malloc操作进行堆空间的存储分配,此时插入执行信号处理函数会发生什么呢?又例如某些将结果存放到静态存储单元中的函数,期间插入执行信号处理程序,在程序中再次在静态存储单元中存放数据,这时会发生什么呢?

上述的两种情况是不可重入的,因为内核维护的堆存储区链表可能正在更改,而第二种情况中存储区可能被覆盖

信号处理函数可以调用的可重入函数
acceptfchmodlseeksendtostat
accessfchownlstatsetgidsymlink
aio_errorfcntlmkdirsetpgidsysconf
aio_returnfdatasyncmkfifosetsidtcdrain
aio_suspendforkopensetsockopttcflow
alarmfpathconfpathconfsetuidtcflush
bindfstatpauseshutdowntcgetattr
cfgetispeedfsyncpipesigactiontcgetpgrp
cfgetospeedftruncatepollsigaddsettcsendbreak
cfsetispeedgetegidposix_trace_eventsigdelsettcsetattr
cfsetospeedgeteuidpselectsigemptysettcsetpgrp
chdirgetgidraisesigfillsettime
chmodgetgroupsreadsigismembertimer_getoverrun
chowngetpeernamereadlinksignaltimer_gettime
clock_gettimegetpgrprecvsigpausetimer_settime
closegetpidrecvfromsigpendingtimes
connectgetppidrecvmsgsigprocmaskumask
creatgetsocknamerenamesigqueueuname
dupgetsockoptrmdirsigsetunlink
dup2getuidselectsigsuspendutime
execlekillsem_postsleepwait
execvelinksendsocketwaitpid
_Exit & _exitlistensendmsgsocketpairwrite

其他大多数函数是不可重入的,主要原因是:

  1. 他们使用静态数据结构
  2. 他们调用 malloc 或 free
  3. 他们是标准IO函数,而标准IO的很多事先都以不可重入方式使用全局数据结构

 

由于线程只有一个 errno 变量,所以信号处理程序可能会修改他的值,因此,作为一个通用规则,信号处理函数应在执行可重入函数之前先保存 errno 的值,并在其后恢复

若在信号处理程序中调用一个不可重入函数,其结果是不可预见的

 






读书笔记      技术帖      linux      unix      龙潭书斋      apue      unix环境高级编程      signal      信号      系统调用      malloc      free      errno     


京ICP备15018585号