I/O基础
1、java1.4之前,java对I/O支持不完善,存在以下问题:
没有数据缓冲区,I/O性能存在问题。
没有C或者C++的channel概念,只有输入输出流。
同步式阻塞式I/O通信,通常会导致通信线程被长时间阻塞。
支持的字符集有限,硬件可移植性不好。
2、Linux网络I/O模型
Linux内核将所有外部设备都看作一个文件来操作,对文件的操作都会调用内核提供的系统命令,返回一个fd(文件描述符)。
描述符就是一个数字,它指向内核中的一个结构体(文件路径,数据区等属性)。
fd演示:
#include
#include
#include
#include
using namespace std;
int main(){
int fd;
fd=open("./test.cpp",O_RDONLY);
cout<
return 0;
}
3、Linux提供了5种网路I/O模型
阻塞I/O模型
用户线程调用内核操作,在内核操作返回之前一直处于阻塞。
非阻塞I/O模型
用户线程调用内核操作,在内核操作返回之前轮询是否有数据返回。
I/O复用模型
Linux提供了select/poll,进程将一个或多个fd传递给select或poll系统调用,
阻塞在select操作上,这样select/poll就可以帮我们侦测多个fd是否处于就绪状态。
select/poll是顺序扫描fd,而且支持的fd数量有限,所以使用上有限制。
Linux还提供了epoll系统调用,基于事件驱动,比顺序轮询效率要高。
信号驱动I/O模型
执行信号函数
异步I/O模型
告知内核启动某个操作,并让内核在整个操作完成之后包括
将数据从内核复制到用户缓冲区通知我们。
4、I/O多路复用技术
服务端将多个客户端线程阻塞复用到同一个select,可以使单线程情况下可以处理多个客户端请求。好处是系统开销小。
I/O多路复用应用场景:
服务器需要同时处理多个处于监听状态或者多个连接字状态的套接字。
服务器需要同时处理多种网络协议的套接字。
epoll优势
1、支持一个进程打开的FD不受限制(仅受限于操作系统的最大文件句柄数)
例如在1GB内存的机器上大约是10万各句柄左右。具体可以通过cat /proc/sys/fs/filemax查看
2、I/O效率不会随着FD数量增大而线性下降。
当你有一个很大的socket集合时,由于网路延时或者链路空闲,
任一时刻只有很少的socket是活跃的,
但是select/poll每次调用时都会线性扫描全部集合,导致效率线性下降。
epoll不存在这个问题,在内核实现中epoll是根据每个fd上的callback函数实现,
只有活跃的socket才会主动去调用callback函数,其他状态的socket则不会。
3、使用mmap加速内核与用户空间的消息传递。
无论是select/poll还是epoll都需要内核把FD消息通知给用户空间,
epoll是通过内核和用户空间mmap同一块内存实现。
4、epoll的API更加简单
包括创建一个epoll描述符、添加监听事、
阻塞等待所监听的事件发生,关闭epoll描述符等。
本文来源于牛客网
作者:图灵95
网友评论