IO模型
作者:互联网
Unix IO模型
对于一个套接字上的输入操作,分为两步:
- 等待数据准备好(从网络中到达,到内核缓冲区)
- 将数据从内核缓冲区复制到应用进程缓冲区
I/O模型主要为以下五种:
- 阻塞I/O
- 非阻塞I/O
- I/O多路复用
- 信号驱动I/O
- 异步I/O
阻塞式I/O
recvfrom
- 系统调用,应用进程从执行系统调用会一直阻塞直到数据被复制到应用进程缓冲区。阻塞期间,CPU处理其他事情。
非阻塞I/O
应用进程执行系统调用后,内核返回错误码EWOULDBLOCK
,应用进程继续执行,但需要不断执行系统调用获知I/O是否完成(即轮询, polling)。会占用更多CPU,CPU要处理很多系统调用。
I/O多路复用
使用select
或者poll
等待数据,并且可以等待多个套接字中的任何一个变为可读,此期间被阻塞。内核通知可读后,应用进程再调用recvfrom
读数据。它使得单个进程具备处理多个I/O事件的能力,又叫做Event Driven I/O。select, poll, epoll都是I/O多路复用的机制。
- select
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select监视的文件描述符有3种,分别是writefds, readfds, exceptfds。调用后,当文件准备好时(可读,可写,except),就返回。返回后,需要遍历fdset来找到哪个就绪了。优点在于基本所有平台都支持。缺点在于一个进程可以监视的文件描述符数量有限,linux一般是1024个。
- poll
int poll (struct pollfd *fds, unsigned int nfds, int timeout);
poll使用一个pollfd指针实现,和select相比实现方式不同,且没有最大数量限制。相同点是返回后都需要遍历pollfd来找到就绪的文件描述符。
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};
- epoll
epoll更加灵活,没有文件描述符限制,将用户关心的文件描述符时间存放在内核的事件表中,在用户空间和内核空间的拷贝只要一次。
/*
*创建一个epoll的句柄
*size用来告诉内核这个监听的数目一共有多大
*size只是对内核初始分配内部数据结构做一个建议,并不限制所能监听的最大文件描述符
*创建好后,epool会占用一个fd
*/
int epoll_create(int size);
/*
*对指定描述符fd进行op操作
*op:ADD, DEL, MOD
*/
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
/*
*等待epfd上的io事件
*/
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
epoll会通过epoll_ctl
注册一个文件描述符,一旦某个文件描述符就绪,内核会采用类似callback的机制,激活这个文件描述符,就省去了select和poll的遍历文件描述符的操作,则其IO效率不会随着监视fd的数量的增长而下降。epoll可以支持的fd在1G内存上大概有10万,可通过cat /proc/sys/fs/file-max
查看。
信号驱动I/O
异步I/O
Java IO多路复用
一些概念
Channel
顾名思义,Channel是一个通道,通道即连接两端,一端为应用程序,另一端则为操作系统。可以说Channel是一个在应用程序和操作系统之间可传递内容,交互事件的通道。一个通道会有一个专属的文件状态描述符。
- ServerSocketChannel : 应用服务器的监听通道,只能关注
OP_ACCEPT
事件 - SocketChannel : TCP Socket套接字的监听通道
文件描述符
Unix/Linux系统为了统一对各种硬件操作,简化接口,将这些硬件设备都看做一个文件。对这些文件的操作,等同于磁盘上普通文件的操作。为了区分不同“文件”,Unix/Linux会为每个文件分配一个ID,这个ID是个整数,即文件描述符(File Descriptor)。例如,通常用0表示标准输入文件如键盘,1表示标准输出文件如显示器。所以,这里“文件”可以代表着一个硬件设备,磁盘上普通文件,甚至网络连接。Windows系统也有类似“文件描述符”的概念,一般被叫做“文件句柄”,但Windows会区分网络连接和文件。
注意:网络连接也是一个文件。可以通过socket()
函数创建一个网路连接或者说打开一个网络文件。
Socket 套接字
Socket原意为插座,它其实就是一个网络连接。或者也可以把Socket直接想象成一个"服务器IP:Port <-> 客户端IP:Port"的网络连接。
Selector
I/O多路复用是应用进程执行系统调用,等待任意一个套接字数据准备好的过程。而Selector在其中充当的角色即为“轮询代理器”,应用进程只需要向Selector注册关注的Channel,Selector内部也维护一个Channel容器,Selector向操作系统询问这些数据准备好没有呀。I/O多路复用需要操作系统支持,不同操作系统的实现细节是不同的,Selector作为轮询代理期,也是一个抽象,屏蔽不同操作系统的差异,都有一个Selector。
参考资料:
IO 模型
Java NIO - IO多路复用
Socket是什么?套接字是什么?
标签:文件,epoll,int,模型,描述符,fd,内核,IO 来源: https://www.cnblogs.com/rachel-aoao/p/io.html