Linux网络编程errno的EAGAIN和EINTR
在Linux环境下开发经常会碰到很多错误(设置errno),其中EAGAIN是其中比较常见的一个错误(比如用在非阻塞操作中)。EAGAIN和 EWOULDBLOCK等效!
从字面上来看,是提示再试一次。这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作(对文件或socket)的时候。例如,以O_NONBLOCK的标志打开文件/socket/FIFO,如果你连续做read操作而没有数据可读。此时程序不会阻塞起来等待数据准备就绪返回,read函数会返回一个错误EAGAIN,提示你的应用程序现在没有数据可读请稍后再试。又例如,当一个系统调用(比如fork)因为没有足够的资源(比如虚拟内存)而执行失败,返回EAGAIN提示其再调用一次(也许下次就能成功)。
Linux - 非阻塞socket编程处理EAGAIN错误
在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN),这是什么意思?
这表明你在非阻塞模式(比如epoll的ET模式下设置recv,对应的fd文件描述符设置为非阻塞)下调用了阻塞操作,在该操作没有完成就返回这个错误,这个错误不会破坏socket的同步,不用管它,下次循环接着recv就可以。对非阻塞socket而言,EAGAIN不是一种错误。在VxWorks和Windows上,EAGAIN的名字叫做EWOULDBLOCK。
EINTR错误:
慢系统调用(slow system call):此术语适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用是指调用有可能永远无法返回,多数网络支持函数都属于这一类。如:若没有客户连接到服务器上,那么服务器的accept调用就没有返回的保证。
- EINTR错误的产生:当阻塞于某个慢系统调用的一个进程捕获某个信号且相应信号处理函数返回时,该系统调用可能返回一个EINTR错误。例如:在socket服务器端,设置了信号捕获机制,有子进程,当在父进程阻塞于慢系统调用时由父进程捕获到了一个有效信号时,内核会致使accept返回一个EINTR错误(被中断的系统调用)。
当碰到EINTR错误的时候,可以采取有一些可以重启的系统调用要进行重启,而对于有一些系统调用是不能够重启的。例如:accept、read、write、select、和open之类的函数来说,是可以进行重启的。不过对于套接字编程中的connect函数我们是不能重启的,若connect函数返回一个EINTR错误的时候,我们不能再次调用它,否则将立即返回一个错误。针对connect不能重启的处理方法是,必须调用select来等待连接完成。
对于socket接口(指connect/send/recv/accept..等等后面不重复,不包括不能设置非阻塞的如select),在阻塞模式下有可能因为发生信号,返回EINTR错误,由用户做重试或终止。
但是,在非阻塞模式下,是否出现这种错误呢?
对此,重温了系统调用、信号、socket相关知识,得出结论是:不会出现。
首先,
- 信号的处理是在用户态下进行的,也就是必须等待一个系统调用执行完了才会执行进程的信号函数,所以就有了信号队列保存未执行的信号;
- 用户态下被信号中断时,内核会记录中断地址,信号处理完后,如果进程没有退出则重回这个地址继续执行;
socket接口是一个系统调用,也就是即使发生了信号也不会中断,必须等socket接口返回了,进程才能处理信号。
也就是,EINTR错误是socket接口主动抛出来的,不是内核抛的。socket接口也可以选择不返回,自己内部重试之类的..
那阻塞的时候socket接口是怎么处理发生信号的?
举例socket接口,例如recv接口会做2件事情,
- 检查buffer是否有数据,有则复制清除返回;
- 没有数据,则进入睡眠模式,当超时、数据到达、发生错误则唤醒进程处理;
socket接口的实现都差不了太多,抽象说,
- 资源是否立即可用,有则返回
- 没有,就等...
对于
1.这个时候不管有没信号,也不返回EINTR,只管执行自己的就可以了
2.采用睡眠来等待,发生信号的时候进程会被唤醒,socket接口唤醒后检查有无未处理的信号(signal_pending)会返回EINTR错误。
所以
socket接口并不是被信号中断,只是调用了睡眠,发生信号睡眠会被唤醒通知进程,然后socket接口选择主动退出,这样做可以避免一直阻塞在那里,有退出的机会。非阻塞时不会调用睡眠。
Linux网络编程errno的EAGAIN和EINTR相关推荐
- Linux网络编程 | 定时事件 :Linux常见定时方法、定时器链表、空闲断开
文章目录 Linux定时方法 定时器链表 空闲断开 Linux定时方法 Linux中为我们提供了三种定时方法,分别是Socket超时选项,SIGALRM信号,I/O复用超时参数.下面一一对其进行介绍. ...
- Linux网络编程——黑马程序员笔记
01P-复习-Linux网络编程 02P-信号量生产者复习 03P-协议 协议: 一组规则. 04P-7层模型和4层模型及代表协议 分层模型结构: OSI七层模型: 物.数.网.传.会.表.应TCP/ ...
- Linux网络编程——千峰物联网笔记
B站视频:千峰物联网学科linux网络编程 网址:https://www.bilibili.com/video/BV1RJ411B761?p=1 目录 第一章:计算机网络概述 1.1计算机网络发展简史 ...
- alin的学习之路(Linux网络编程:十)(http协议,BS模型)
alin的学习之路(Linux网络编程:十)(http协议,BS模型) 需求:使用B/S模型来访问主机中的文件(包括目录) 0. B/S 模型 注意事项 1. 浏览器请求ico 准备一个favic ...
- linux网络编程--阻塞与非阻塞
linux网络编程--阻塞与非阻塞 建立连接 接受连接 无阻塞的设置方式 read() write() 读操作 写操作 Linux fcntl函数详解 功能描述 函数原型 fcntl()函数五种功能 ...
- Linux网络编程---I/O复用模型之epoll
https://blog.csdn.net/men_wen/article/details/53456474 Linux网络编程-I/O复用模型之epoll 1. epoll模型简介 epoll是Li ...
- linux网络编程(二)高并发服务器
linux网络编程(二)高并发服务器 错误处理 高并发服务器 多进程并发服务器 客户端 错误处理 #include "wrap.h"int Bind(int fd, const s ...
- Linux网络编程基础
2019独角兽企业重金招聘Python工程师标准>>> (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端 网络程序和普通的程序有一个最大的 ...
- Linux网络编程-七
Linux网络编程-七 web服务器项目 1 web服务器开发准备 1.1 Html语言基础(和Markdown一个性质,某些程度上和Markdown通用,所以我在编辑的时候在<>里都加了 ...
最新文章
- 洗礼灵魂,修炼python(54)--爬虫篇—urllib2模块
- 你真的会发朋友圈吗?
- 19、深入理解计算机系统笔记,虚拟存储器,基本原理(1)
- python,numpy中np.random.choice()的用法详解及其参考代码
- Redis详解(三)——Redis持久化
- html psd设计图,根据PSD登陆页面设计稿切图制作HTML网页全过程
- SWAT模型非点源模拟原理
- AmiGO2:在线浏览和查询GO信息的利器
- 输入法linux debin,Debian下安装搜狗拼音输入法
- cmf php,php cmf
- Alsa 调试下篇:应用篇
- 工欲善其事必先利其器
- Fiddler功能讲解
- AutoJs 4.1.1 实战教程、Hamibot
- Web前端:HTML+CSS+JS实现美女照片3D立方体旋转
- flutter 返回桌面
- Three.js入门指南
- Msc.Marc的python开发#1
- 动物 v.s. AI奥运会:你会赌一只鸟还是机器人夺冠?
- 关于赚钱这件事情,一定要行动起来,别总是想而不做
热门文章
- 软件测试基础测试方法之等价类划分法
- yoloV5改进-针对小目标的NWD
- ppt正在与服务器连接确定信息,dreamwaver 做网站解析9.ppt
- 记把HTTP到HTTPS协议,在Linux服务器中部署阿里申请的免费SSL证书(Tomcat版)
- 2021.5.9数仓之机器详情ODS EDS DM分层设计
- rockwell ab 的AOP, EDS, FIRMWARE
- 鸿蒙成功的概率不大,中国企业能推出成功的操作系统、数据库吗?
- 路由器的基本配置(一)---路由器的简单连接
- 如何修改AD中PCB背景黑色域的大小
- Leetcode题库——17.电话号码的字母组合