利用reactor模式模拟异步IO
http://www.artima.com/articles/io_design_patterns.html
系统函数:
http://linux.die.net/man/4/epoll
在一个非阻塞的socket上调用read/write函数, 返回EAGAIN或者EWOULDBLOCK(注: EAGAIN就是EWOULDBLOCK)
从字面上看, 意思是:EAGAIN: 再试一次,EWOULDBLOCK: 如果这是一个阻塞socket, 操作将被block,perror输出: Resource temporarily unavailable
总结:
这个错误表示资源暂时不够,能read时,读缓冲区没有数据,或者write时,写缓冲区满了。遇到这种情况,如果是阻塞socket,read/write就要阻塞掉。而如果是非阻塞socket,read/write立即返回-1, 同时errno设置为EAGAIN。
所以,对于阻塞socket,read/write返回-1代表网络出错了。但对于非阻塞socket,read/write返回-1不一定网络真的出错了。可能是Resource temporarily unavailable。这时你应该再试,直到Resource available。
综上,对于non-blocking的socket,正确的读写操作为:
读:忽略掉errno = EAGAIN的错误,下次继续读
写:忽略掉errno = EAGAIN的错误,下次继续写
对于select和epoll的LT模式,这种读写方式是没有问题的。但对于epoll的ET模式,这种方式还有漏洞。
epoll的两种模式LT和ET
二者的差异在于level-trigger模式下只要某个socket处于readable/writable状态,无论什么时候进行epoll_wait都会返回该socket;而edge-trigger模式下只有某个socket从unreadable变为readable或从unwritable变为writable时,epoll_wait才会返回该socket。
所以,在epoll的ET模式下,正确的读写方式为:
读:只要可读,就一直读,直到返回0,或者 errno = EAGAIN
写:只要可写,就一直写,直到数据发送完,或者 errno = EAGAIN
作者:郭无心
链接:http://www.zhihu.com/question/22524908/answer/69054646
来源:知乎
水平触发(level-triggered,也被称为条件触发)LT: 只要满足条件,就触发一个事件(只要有数据没有被获取,内核就不断通知你)
边缘触发(edge-triggered)ET: 每当状态变化时,触发一个事件。
Java的NIO属于水平触发,即条件触发
所以在使用Java的NIO编程的时候,在没有数据可以往外写的时候要取消写事件,在有数据往外写的时候再注册写事件。
select 最不能忍受的是一个进程所打开的FD是有一定限制的,由FD_SETSIZE设置,默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显然太少了。这时候你一是可以选择修改这个宏然后重新编译内核,不过资料也同时指出这样会带来网络效率的下降
不过 epoll则没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,不过由于网络延时,任一时间只有部分的socket是"活跃"的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数,其他idle状态socket则不会
使用mmap加速内核与用户空间的消息传递。
这点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。
分享到:
相关推荐
在 Linux 开发领域,技术人员尤为关注几个关键性能指标:进程管理、CPU 使用率、内存占用、网络 I/O 和磁盘 I/O。其中,磁盘 I/O 性能尤其重要,因为它直接影响到系统的响应速度和整体性能。本文旨在全面、深入地...
它继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统,Linux是许多企业和服务提供商的首选操作系统,用于部署Web服务器、数据库服务器、邮件服务器等。Linux系统具有高效的网络功能和稳定的...
1. **I/O模拟与测试**:它可能允许用户模拟各种I/O操作,例如对硬盘、网络、串口或并口的读写,以便在不同场景下测试硬件的响应速度和稳定性。 2. **性能监控**:如同`ru`一样,`abu-1.0`可能会实时展示I/O操作的...
在Linux中,一切皆为文件,包括硬件设备、网络接口等,都被抽象为文件。这种设计使得Linux系统的可扩展性和通用性极强。文件系统是用于组织和管理这些文件的机制,例如EXT4、XFS等。 在Linux中进行文件I/O操作,...
### Linux文件IO操作详解 #### 基本概念 Linux 文件 I/O 操作是学习 Linux 应用开发的基础,尤其对于初学者来说至关重要。本文旨在详细介绍 Linux 下的文件 I/O 操作及其相关概念。 #### 文件 在 Linux 系统中,...
### Linux网络编程之IO复用循环服务器 #### 一、引言 在现代网络应用开发中,服务器的设计面临着越来越高的并发请求处理需求。传统的简单循环服务器每次只能处理一个客户端请求,这种方式显然无法满足高并发场景的...
Linux IO 模型与网络模型 Linux IO 模型是指在 Linux 操作系统中,进程与硬件设备之间的交互方式。不同的 IO 模型对系统性能和可靠性都有很大的影响。在 Linux 中,IO 模型可以分为阻塞 IO、非阻塞 IO、异步 IO 等...
5. **硬件层**:包括磁盘、网络适配器等物理设备,是IO操作的实际执行者。 #### 二、块IO层——截获IO 块IO层是Linux IO架构中的核心组成部分之一,它位于文件系统层和设备驱动层之间。该层的主要功能包括: 1. *...
从给定的文件信息中,我们可以提炼出一系列关于Linux操作系统的关键知识点,主要集中在进程、线程、网络编程以及系统管理方面。以下是对这些知识点的详细阐述: ### Linux进程与线程 #### 进程 在Linux系统中,...
除了传统的块设备 I/O,Linux 还支持网络 I/O,包括 NFS、Coda、SMBFS 等。这些协议允许用户通过网络访问远程文件系统,从而实现了分布式文件系统的功能。 #### 十、特殊用途文件系统 Linux 还包含了一些特殊用途的...
在Linux操作系统中,I/O(Input/Output)编程是系统编程的重要组成部分,它涉及到进程与外部设备之间的数据...通过阅读“linux的IO编程(新版).pdf”,你应该能够深入理解这些概念,并学会如何在实际项目中应用它们。
在Linux环境下,网络I/O(Input/Output)模型是系统处理网络数据传输的关键部分,它涉及到如何高效地读取和写入网络数据。本主题将深入探讨几种主要的网络I/O模型,包括阻塞I/O、非阻塞I/O、I/O复用、信号驱动I/O...
【基于Linux的RapidIO技术】深入解析 RapidIO是一种高速互连技术,最初由摩托罗拉(现飞思卡尔半导体)开发,主要用于嵌入式系统,特别是电信级设备,如4G LTE的eNodeB设备。RapidIO提供了一个基于消息的接口,能够...
Linux网络基础和网络编程是IT领域中的重要组成部分,特别是在服务器端开发中不可或缺。本文将深入探讨这个主题,从Linux网络的基础知识开始,逐步讲解到Socket编程以及如何实现高并发服务器。 1. Linux网络基础: ...
Linux内核中的驱动分为字符设备驱动、块设备驱动、网络设备驱动等。它们通常包含初始化函数、读写操作函数、设备控制函数等,这些函数通过系统调用接口与用户空间交互。 3. **访问ARM端口** 在ARM架构中,硬件...
在Linux中,有五种主要的IO模型:阻塞IO、非阻塞IO、IO复用(如select、poll、epoll)、信号驱动IO和异步IO。每种模型都有其适用场景和优缺点。例如,阻塞IO简单易用,但会阻塞进程直到数据准备就绪;非阻塞IO不会...