漫画网站模板,搜索引擎优化有哪些,多媒体设计与制作毕业设计,中企动力做的保安服务网站1、介绍慢系统调用
该术语适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用是指调用永远无法返回#xff0c;多数网络支持函数都属于这一类。如#xff1a;若没有客户连接到服务器上#xff0c;那么服务器的accept调用就会一直阻塞。 慢系统调用可以被永久阻塞#…1、介绍慢系统调用
该术语适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用是指调用永远无法返回多数网络支持函数都属于这一类。如若没有客户连接到服务器上那么服务器的accept调用就会一直阻塞。 慢系统调用可以被永久阻塞包括以下几个类别 1读写‘慢’设备包括pipe终端设备网络连接等。读时数据不存在需要等待写时缓冲区满或其他原因需要等待。读写磁盘文件一般不会阻塞。 2当打开某些特殊文件时需要等待某些条件才能打开。例如打开中断设备时需要等到连接设备的modem响应才能完成。 3pause和wait函数。pause函数使调用进程睡眠直到捕获到一个信号。wait等待子进程终止。 4某些ioctl操作。 5某些IPC操作。 2、EINTR错误产生的原因
如果进程在一个慢系统调用(slow system call)中阻塞时当捕获到某个信号且相应信号处理函数返回时这个系统调用被中断调用返回错误设置errno为EINTR相应的错误描述为“Interrupted system call”。 如下表所示的系统调用就会产生EINTR错误当然不同的函数意义也不同。 系统调用函数 errno为EINTR表征的意义
write
由于信号中断没写成功任何数据。The call was interrupted by a signal before any data was written.
open由于信号中断没读到任何数据。
The call was interrupted by a signal before any data was read.
recv由于信号中断返回没有任何数据可用。
The receive was interrupted by delivery of a signal before any data were available.
sem_wait函数调用被信号处理函数中断。
The call was interrupted by a signal handler. 3、解决办法
既然系统调用会被中断那么别忘了要处理被中断的系统调用。有三种处理方式 1 人为重启被中断的系统调用 当碰到EINTR错误的时候有一些可以重启的系统调用要进行重启而对于有一些系统调用是不能够重启的。例如accept、read、write、select、和open之类的函数来说是可以进行重启的。不过对于套接字编程中的connect函数我们是不能重启的若connect函数返回一个EINTR错误的时候我们不能再次调用它否则将立即返回一个错误。针对connect不能重启的处理方法是必须调用select来等待连接完成。
理解“重启” 一些IO系统调用执行时如 read 等待输入期间如果收到一个信号系统将中断read 转而执行信号处理函数. 当信号处理返回后 系统遇到了一个问题 是重新开始这个系统调用 还是让系统调用失败早期UNIX系统的做法是 中断系统调用并让系统调用失败 比如read返回 -1 同时设置 errno 为EINTR中断了的系统调用是没有完成的调用它的失败是临时性的如果再次调用则可能成功这并不是真正的失败所以要对这种情况进行处理 典型的方式为如下我们采用accept函数为例子代码如下 ACCEPT:clifd accept(srvfd,(struct sockaddr*)cliaddr,cliaddrlen);if (clifd -1) {if (errno EINTR) {goto ACCEPT;} else {fprintf(stderr, accept fail,error:%s\n, strerror(errno));return -1;}} 2 安装信号时设置 SA_RESTART属性该方法对有的系统调用无效 struct sigaction action; action.sa_handler handler_func; sigemptyset(action.sa_mask); action.sa_flags 0; /* 设置SA_RESTART属性 */ action.sa_flags | SA_RESTART; sigaction(SIGALRM, action, NULL); 并不是所有的都有效 3 忽略信号让系统不产生信号中断 struct sigaction action; action.sa_handler SIG_IGN; sigemptyset(action.sa_mask); sigaction(SIGALRM, action, NULL); 所以建议大家用第一种方法重启。