对于io模型这块内容之前基本完全没有接触过,有了些许了解之后还是很困昏,select、poll、epoll的关系以及服务器ngnix、apache的工作机制,还有JAVA NIO、BIO、AIO这么多的概念混杂起来实在是不好理解,想稍微梳理一下。 网络IO模型 网络IO的本质是socket的读取,socket在linux系统被抽象为流,IO可以理解为对流的操作 IO其实我们并不陌生,站在操作系统的角度上说,io一般指访问磁盘数据,可以分为两步,以read操作举例的话: 第一阶段:等待数据准备 (Waiting for the data to be ready)。 第二阶段:将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)。 而网络IO也是如此,只不过它是读取的不是磁盘,而是socket: 第一步:通常涉及等待网络上的数据分组到达,然后被复制到内核的某个缓冲区。 第二步:把数据从内核缓冲区复制到应用进程缓冲区。 在理解网络IO模型之前,我们得先准备些IO模型的基础知识 IO模型 Unix 有五种 I/O 模型: 阻塞IO(bloking IO) 非阻塞IO(non-blocking IO) 多路复用IO(multiplexing IO) 信号驱动式IO(signal-driven IO) 异步IO(asynchronous IO) 每个 IO 模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点。下面提供一个简单的图片以供了解。 image 阻塞式 IO 应用进程被阻塞,直到数据复制到应用进程缓冲区中才返回。 应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。 下图中,recvfrom 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。 [图片上传失败...(image-111ada-1538122299754)] 非阻塞式 IO 应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。 由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率是比较低的。 [图片上传失败...(image-76babc-1538122299754)] 多路复用IO 由于阻塞式IO通过轮询得到的只是一个IO任务是否完成,而可能有多个任务在同时进行,因此就想到了能否轮询多个IO任务的状态,只要有任何一个任务完成,就去处理它。这就是所谓的IO多路复用。LINUX下具体的实现方式就是select、poll、epoll。 这种机制可以让单个进程具有处理多个 IO 事件的能力。