名词解释
BIO: Blocking IO 即阻塞IO,准确的说是同步阻塞IO NIO: NonBlocking IO 即非阻塞IO,准确的说是同步非阻塞IO AIO: Asynchronous IO 即异步IO,准确的说是异步非阻塞IO
阻塞: 简单来说,就是当你发起一个任务(命令/请求/操作)的时候,无论任务是否由你完成,你都得等着,直到任务完成。 非阻塞: 跟阻塞相反,就是当你发起一个任务时,交给其他人去做,你可以去做其他的事儿,但是时不时的还得回来看看做完了没(这一步就叫做轮询)。 异步: 异步这个词有很多意思,在当前场景下,意思就是当你发起一个任务时,交给其他人去做,你就可以去做别的事儿了,其他人做好之后,会直接送到你手上。
多路复用: 基于同步非阻塞IO的一种应用,在同步非阻塞场景下,轮询会占用大部分的处理时间,当有大量的IO请求时,每个线程都需要不停的轮询数据是否处理完毕。此时,可以将所有的IO操作合并到一个(或多个)线程中,这个线程一般称之为IO线程,由它去轮询每个IO操作的状态,一旦有某个操作已经完成,则唤起对应的工作线程去处理,这就是多路复用。
阻塞与非阻塞
IO操作的处理流程一般有两步,第一是接受IO请求,等待数据传输,这个阶段可以称之为准备数据,第二是数据传输完毕后,读取数据到内存进行后续操作,这个阶段可以称之为读取数据。阻塞与非阻塞就是在这两个过程中产生了不同的行为。阻塞是指在第一阶段及第二阶段时,进程或线程都需要等待,直到读取数据完毕后才能进行下一步动作;非阻塞一般是指第一阶段准备数据时,进程可以交由底层操作系统完成,但需要不断的轮询数据是否准备完成,之后的读取数据阶段则是阻塞的;而异步IO则是将第一阶段及第二阶段都由底层操作系统完成,操作系统负责准备数据并且读取数据到对应内存中,然后通知工作进程数据读取完毕,工作进程去进行下一步动作。
多路复用
多路复用,一般是通过一些系统函数,比如select,poll,epoll等完成,至于这三者的区别,这里就不展开了,大致介绍一下: select通过一种类似数组的方式来存储所有的socket,因此有一个最大连接数的限制(当然,这个上限可以通过修改内核代码来进行扩充,但是属于野路子了吧),同时采用轮询的方式查看每个socket是否活跃。 poll与select相比,改进在于使用了链表来存储所有的socket,因此没有一个硬性的最大连接数的限制,不过由于poll也是使用轮询的方式来处理所有的socket,因此当socket数量不断增大时,性能会受到较大影响。 epoll一个最大的特点在于回调机制,活跃socket产生的事件会触发注册的回调,从而通知操作系统进行处理。由于回调机制的存在,epoll只需要处理活跃的socket,而不需要对不活跃的socket进行处理,大大提升了在网络环境下的吞吐量。
代码示例
todo