本文内容有借鉴《Netty权威指南》的部分内容
Linux网络IO模型
首先说一下一个文件描述符(file descriptor)fd的概念,在Linux中,一切都可以视作文件,对一个文件的读写操作就会调用内核提供的系统命令,返回一个fd,使用socket也会有fd,描述符就是一个数字,指向核内的一个结构体(文件路径,数据区等一些属性)
阻塞IO模型
最常用的IO模型,也是默认情况下的,详细说就是我们说的一个连接一个线程的模型,每一个系统调用的执行都必须在内核等待数据准备号,然后才进行下面的操作。
非阻塞IO模型
在一个操作的执行中,发起一个系统调用到内核,如果数据没有准备号,直接返回,不等待。这个模型中,我们通常需要使用一个轮询检查内核的数据状态,看是否准备好。
IO复用模型
Linux提供select/poll进程通过将一个fd或多个fd传递给select/poll系统调用,将会阻塞在select上,这样就可以侦测多个fd是否在就绪状态,select/poll是顺序检查,而且支持的fd有上限。为此还有一个epoll系统调用,它是基于事件驱动的,具体下面说.
信号驱动IO模型
是这样的一个过程,首先开启套接字信号驱动功能,并通过系统调用sigaction执行一个信号处理函数,但这个过程并不阻塞,执行完就返回了,当内核中数据准备好了,通过信号回调通知程序来取数据.
异步IO
告诉内核某个操作,并让内核在整个操作完成后通知我们.与信号调用是不同的,信号调用只是通知数据准备好了,具体的操作还得自己做,但是异步IO直接是完成任务后通知.
IO多路复用技术
有select,pselect,poll,epoll系统调用,主要的过程就是上面的IO复用模型,说下几个区别
- fd上限
- select : 32位1024,64位2048个epoll并没有这个限制,虽然不是绝对的无上限,但是大到不用考虑这个问题
- 效率: select/poll是一个轮询检查的过程,当有一个很大的fd集合,但是活跃的又没多少个,这时,select的效率就很低了,但是在同样的情况下,使用epoll就很好,上面也说到了,epoll是事件驱动的,也就是说有一个回调的过程,epoll有三个函数,
epoll_create
,epoll_ctl
,epoll_wait
,create是一个创建epoll的过程,当调用ctl的时候,将用户态的fd发送到内核态,这些fd会有一个回调函数,当准备好的时候,将其fd加入到一个就绪队列中,当使用wait时,我们只检查这些就绪队列中的fd,很显然,效率不是一个层面的 - 内存复制的不同,epoll会使用mmap实现公用内存,mmap是零拷贝技术的一种
- 加一篇博客: IO多路复用,很详细