socket中的函数遇见EINTR的处理

这几天,写服务器代码过程当中,遇见EINRT信号的问题,我是借鉴 《unp 》,采用continue或者goto again循环解决的。但是感觉这个还是很有必要记录一下。网络上查找到的信息很多。下面是我查找到的和EINTR有关的介绍:
1  http://blog.csdn.net/yanook/article/details/7226019   慢系统调用函数如何处理中断信号EINTR
2  http://blog.csdn.net/benkaoya/article/details/17262053  信号中断 与 慢系统调用
3  http://1.guotie.sinaapp.com/?p=235     socket,accept,connect出现EINTR错误的解决方法
个人认为2说的比较明确,建议大家多看看。
我的记录基本上是对2的抄袭:

慢系统调用:可能永远阻塞的系统调用
这很关键,不适用于非诸塞的情况。 永远阻塞的系统调用是指调用永远无法返回,多数网络支持函数都属于这一类。如:若没有客户连接到服务器上,那么服务器的accept调用就会一直阻塞。
(以下为抄袭2原文)

EINTR说明:
如果进程在一个慢系统调用(slow system call)中阻塞时,当捕获到某个信号且相应信号处理函数返回时,这个系统调用被中断,调用返回错误,设置errno为EINTR(相应的错误描述为“Interrupted system call”)。

怎么看哪些系统条用会产生EINTR错误呢?man 7 signal,在ubuntu 10.04上可以查看,哪些系统调用会产生 EINTR错误。

如何处理被中断的系统调用

既然系统调用会被中断,那么别忘了要处理被中断的系统调用。有三种处理方式:

◆ 人为重启被中断的系统调用

◆ 安装信号时设置 SA_RESTART属性(该方法对有的系统调用无效)

◆  忽略信号(让系统不产生信号中断)

人为重启被中断的系统调用

人为当碰到EINTR错误的时候,有一些可以重启的系统调用要进行重启,而对于有一些系统调用是不能够重启的。例如:accept、read、write、select、和open之类的函数来说,是可以进行重启的。不过对于套接字编程中的connect函数我们是不能重启的,若connect函数返回一个EINTR错误的时候,我们不能再次调用它,否则将立即返回一个错误。针对connect不能重启的处理方法是,必须调用select来等待连接完成。

这里的“重启”怎么理解?

一些IO系统调用执行时,如 read 等待输入期间,如果收到一个信号,系统将中断read, 转而执行信号处理函数. 当信号处理返回后, 系统遇到了一个问题: 是重新开始这个系统调用, 还是让系统调用失败?早期UNIX系统的做法是, 中断系统调用,并让系统调用失败, 比如read返回 -1, 同时设置 errno 为EINTR中断了的系统调用是没有完成的调用,它的失败是临时性的,如果再次调用则可能成功,这并不是真正的失败,所以要对这种情况进行处理, 典型的方式为:

另外,原文建议上去github上看看别人怎么处理EINTR错误的,下面2个处理方面均是截图过来的:

connect处理方式,抄袭3原文,没有测试过,处理方法是对的。
connect的问题,当connect遇到EINTR错误时,不能向上面那样重新进入循环处理,原因是,connect的请求已经发送向对方,正在等待对方回应,这是如果重新调用connect,而对方已经接受了上次的connect请求,这一次的connect就会被拒绝,因此,需要使用select或poll调用来检查socket的状态,如果socket的状态就绪,则connect已经成功,否则,视错误原因,做对应的处理。
#include poll.hint check_conn_is_ok(socket_t sock) {struct pollfd fd;int ret = 0;socklen_t len = 0;fd.fd = sock;fd.events = POLLOUT;while ( poll (&fd, 1, -1) == -1 ) {if( errno != EINTR ){perror("poll");return -1;}}len = sizeof(ret);if ( getsockopt (sock, SOL_SOCKET, SO_ERROR,&ret,&len) == -1 ) {perror("getsockopt");return -1;}if(ret != 0) {fprintf (stderr, "socket %d connect failed: %s\n",sock, strerror (ret));return -1;}return 0;
}

在调用connect时,这样使用:

#include erron.h....
if(connnect()) {if(errno == EINTR) {if(check_conn_is_ok() < 0) {perror();return -1;}else {printf("connect is success!\n");}}else {perror("connect");return -1;}
}
我一般使用continue或者goto来处理。

安装信号时设置 SA_RESTART属性

我们还可以从信号的角度来解决这个问题,  安装信号的时候, 设置 SA_RESTART属性,那么当信号处理函数返回后, 不会让系统调用返回失败,而是让被该信号中断的系统调用将自动恢复。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct sigaction action;  
  2.    
  3. action.sa_handler = handler_func;  
  4. sigemptyset(&action.sa_mask);  
  5. action.sa_flags = 0;  
  6. /* 设置SA_RESTART属性 */  
  7. action.sa_flags |= SA_RESTART;  
  8.    
  9. sigaction(SIGALRM, &action, NULL);  

但注意,并不是所有的系统调用都可以自动恢复如msgsnd喝msgrcv就是典型的例子,msgsnd/msgrcv以block方式发送/接收消息时,会因为进程收到了信号而中断。此时msgsnd/msgrcv将返回-1,errno被设置为EINTR。且即使在插入信号时设置了SA_RESTART,也无效。在man msgrcv中就有提到这点:

msgsnd and msgrcv are never automatically restarted after being interrupted by a signal handler, regardless of the setting  of the SA_RESTART flag when establishing a signal  handler.

忽略信号

当然最简单的方法是忽略信号,在安装信号时,明确告诉系统不会产生该信号的中断。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct sigaction action;  
  2.    
  3. action.sa_handler = SIG_IGN;  
  4. sigemptyset(&action.sa_mask);  
  5.    
  6. sigaction(SIGALRM, &action, NULL);  
测试代码1
  1. #include <signal.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <error.h>  
  5. #include <string.h>  
  6. #include <unistd.h>  
  7.    
  8. void sig_handler(int signum)  
  9. {  
  10.     printf("in handler\n");  
  11.     sleep(1);  
  12.     printf("handler return\n");  
  13. }  
  14.    
  15. int main(int argc, char **argv)  
  16. {  
  17.     char buf[100];  
  18.     int ret;  
  19.     struct sigaction action, old_action;  
  20.    
  21.     action.sa_handler = sig_handler;  
  22.     sigemptyset(&action.sa_mask);  
  23.     action.sa_flags = 0;  
  24.     /* 版本1:不设置SA_RESTART属性 
  25.      * 版本2:设置SA_RESTART属性 */  
  26.     //action.sa_flags |= SA_RESTART;  
  27.    
  28.     sigaction(SIGALRM, NULL, &old_action);  
  29.     if (old_action.sa_handler != SIG_IGN) {  
  30.         sigaction(SIGALRM, &action, NULL);  
  31.     }  
  32.     alarm(3);  
  33.      
  34.     bzero(buf, 100);  
  35.    
  36.     ret = read(0, buf, 100);  
  37.     if (ret == -1) {  
  38.         perror("read");  
  39.     }  
  40.    
  41.     printf("read %d bytes:\n", ret);  
  42.     printf("%s\n", buf);  
  43.    
  44.     return 0;  
  45. }  
在ubuntu 10.04 上测试结果:
不设置 SA_RESTART,执行结果如下:

说明接受信号处理完成以后,主函数收到EINTR信号,read函数返回-1,退出
设置 SA_RESTART,执行结果如下:

说明设置 SA_RESTART参数以后自动重新调用read函数,没有体现在应用层代码中,在应用层看来,这个EINTR没有造成任何影响。

个人认为下面的总结很重要:

慢系统调用(slow system call)会被信号中断,系统调用函数返回失败,并且errno被置为EINTR(错误描述为“Interrupted system call”)。

处理方法有以下三种:①人为重启被中断的系统调用;②安装信号时设置 SA_RESTART属性;③忽略信号(让系统不产生信号中断)。

有时我们需要捕获信号,但又考虑到第②种方法的局限性(设置 SA_RESTART属性对有的系统无效,如msgrcv),所以在编写代码时,一定要“人为重启被中断的系统调用”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/433111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue 如何获取图片的原图尺寸_公众号封面图片尺寸是多少?如何在公众号里制作封面图?...

公众号文章封面图是自己动手制作还是直接使用网络图片呢&#xff1f;在刚开始接触公众号运营时&#xff0c;我的大部分插图和封面图都是直接选择网络图片&#xff0c;后来才发现&#xff0c;自己制作的封面图更能传达文章的内容&#xff0c;阅读效果更好。其实很多做公众号的人…

主机名排序

主机名排序 主机名由多级域名组成&#xff0c;自右向左&#xff0c;依次是顶级域名、二级域名、三级域名…..以此类推 例&#xff0c;主机名&#xff1a;google.com.hkhk是顶级域名 com是二级域名 google是三级域名 现在我们需要实现一个主机名的排序功能 排序规则 1&#xff…

《计算机应用》实践考核,《管理系统中计算机应用》实践性环节考核方案

一、参考教材&#xff1a;《管理系统中计算机应用》&#xff0c;汪星明、周山芙主编&#xff0c;武汉大学出版社2004年版。二、考核时间&#xff1a;50分钟。三、考核内容及分数分布&#xff1a;1、Windows资源管理器的综合应用(10分)1)启动资源管理器。2)熟练掌握文件(夹)的建…

信号中断 与 慢系统调用

1. 术语 1.1. 慢系统调用&#xff08;Slow system call&#xff09; 该术语适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用是指调用永远无法返回&#xff0c;多数网络支持函数都属于这一类。如&#xff1a;若没有客户连接到服务器上&#xff0c;那么服务器的accept调用…

delete hive_Hive高级调优

Hive调优策略Hive作为大数据领域常用的数据仓库组件&#xff0c;在设计和开发阶段需要注意效率。影响Hive效率的不仅仅是数据量过大;数据倾斜、数据冗余、job(小文件多)或I/O过多、MapReduce分配不合理等因素都对Hive的效率有影响。对Hive的调优既包含对HiveQL语句本身的优化&a…

联想计算机如何设置用户名和密码,联想电脑怎样设密码?联想电脑设置密码方法步骤【图文】...

现代 人最重要的是什么呢?在笔者看来是隐私。如今由于我们的社会比较发达&#xff0c;而信息传播的速度有非常广泛&#xff0c;加上各种隐私被盗取或者偷窥&#xff0c;让现代人的生活总是充斥着不安&#xff0c;所以我们各类的电子设备诸如手机&#xff0c;电脑加密是非常有必…

linux中errno使用

当linux中的C api函数发生异常时,一般会将errno变量(需include errno.h)赋一个整数值,不同的值表示不同的含义,可以通过查看该值推测出错的原因&#xff0c;在实际编程中用这一招解决了不少原本看来莫名其妙的问题。但是errno是一个数字&#xff0c;代表的具体含义还要到errno.…

unity3d 捕获系统日志,来处理一些问题

注册系统日志回调&#xff0c;根据日志内容和类型处理一些特殊问题 using UnityEngine; using System.Collections;public class SetupVerification : MonoBehaviour {public string message "";private bool badSetup false;void Awake (){Application.RegisterL…

em算法 实例 正态分布_EM算法解GMM

看了很多介绍EM算法的文章&#xff0c;但是他们都没有代码&#xff0c;所以在这里写出来。Jensen 不等式参考期望最大算法Jensen不等式在优化理论中大量用到&#xff0c;首先来回顾下凸函数和凹函数的定义。假设 是定义域为实数的函数&#xff0c;如果对于所有的 &#xff0c; …

html5 webview,HTML5+学习历程之webview经典案例

看了这么多app&#xff0c;其实基本布局使用的最多的无非两种&#xff0c;如下图&#xff1a;类似微信类似QQ在这里小编简单说下这两种布局简单的实现思路&#xff0c;当然如果你还有更好的方法&#xff0c;请在下面留言&#xff0c;让更多人知道你更好的方法&#xff01;第一种…

C函数的实现(strcpy,atoi,atof,itoa,reverse)

在笔试面试中经常会遇到让你实现C语言中的一些函数比如strcpy&#xff0c;atoi等 1. atoi 把字符串s转换成数字 int Atoi( char *s ) {int num 0, i 0;int sign 1;for( i0; isspace(s[i]); i );sign (s[i] -)? -1:1;if( s[i] || s[i] - )i;for( ;isdigit(s[i]); i ){n…

bbb sdk6 ll_rw_block分析

ll_rw_block是文件系统对下访问实际的块设备驱动的接口&#xff0c;应用程序对实际文件&#xff08;非设备文件&#xff09;的操作&#xff0c;最终都是 通过文件系统来调用ll_rw_block来操作实际的存储设备的。 当然ll_rw_block的实际作用远非一个接口那么简单&#xff0c;他…

wifi 小米pro 驱动 黑苹果_搞定小米黑苹果自带WIF,又可省一个USB接口了

首先声明我的是小米笔记本PRO版本的&#xff0c;其他版本的没有经过测试&#xff0c;但理论都是没有问题的&#xff0c;其他版本的朋友&#xff0c;喜欢折腾的话&#xff0c;可以试试&#xff01;自用版本关于小米笔记本安装黑苹果&#xff0c;网上一直都有很多链接&#xff0c…

教师资格证计算机考察知识点,教师资格证考试信息技术常考知识点同步练习题.docx...

教师资格证考试信息技术常考知识点同步练习题一、信息的定义及特征( 一) 信息定义信息是通过文字、数字、图像、图形、声音、视频等方式进行传播的内容。说明&#xff1a;信息定义考查的方式有两类&#xff1a;一类是选出四个选项中是信息的 ; 另一类是判断选择题&#xff0c;选…

machine learning for hacker记录(4) 智能邮箱(排序学习推荐系统)

本章是上一章邮件过滤技术的延伸&#xff0c;上一章的内容主要是过滤掉垃圾邮件&#xff0c;而这里要讲的是对那些正常的邮件是否可以加入个性化元素&#xff0c;由于每个用户关心的主题并非一样&#xff08;有人喜欢技术类型的邮件或者购物促销方便的内容邮件等&#xff09;。…

代理模式 委派模式 策略模式_策略模式

在策略模式(Strategy Pattern)中&#xff0c;一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中&#xff0c;我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。介绍意…

云南计算机专业知识真题,2014年云南省事业单位考试专计算机专业知识模拟真题.doc...

2014年云南省事业单位考试专计算机专业知识模拟真题1 在Word中替换的快捷键是____。A、CTRLFB、CTRLHC、CTRLSD、CTRLP2 在Word中打印的快捷键是____。A、CTRLFB、CTRLHC、CTRLOD、CTRLP3 在Word中打开新文档的快捷键是____。A、CTRLFB、CTRLHC、CTRLOD、CTRLP4 在Word中&#…

bbb mmc_blk_probe 分析

bbb 的 emmc驱动在drivers\mmc\card\block.c&#xff0c;其mmc_dirver结构体如下&#xff0c; 根据以往平台总线驱动模型的经验来看的话&#xff0c;内核里应该有mmc_devices结构体&#xff0c;并且 其name也为"mmcblk"&#xff0c;这样其probe函数将被调用&#x…

培智学校计算机课教案,培智数学教案

教学内容&#xff1a;11—20以内数的认识 写数 教学目的&#xff1a;1、使学生能初步地数、读、写(本节课重点看图写20以内的数。) 2、初步会写小棒图、数位表上的数&#xff0c;掌握20以内数的顺序。3、初步简单掌握20以内数的组成。 教学重点&#xff1a;学生看图会数数量并会…

例2-1

#include<stdio.h> int main(void) {printf("Hello World!\n");return 0; } 转载于:https://www.cnblogs.com/520zy/p/3348951.html