目录
IO的过程
- 数据的准备过程
- 数据从内核缓冲区拷贝到用户进程缓冲区的过程
阻塞与非阻塞IO
阻塞IO
当用户进程执行read操作的时候,该用户进程会被阻塞。一直等到内核数据准备好,并将数据从内核缓冲区拷贝到用户缓冲区中后,read操作才返回,进程往下执行。
- 阻塞等待的是内核数据准备完成,并且将数据从内核态拷贝到用户态的这两个过程。
非阻塞IO
当用户进程执行read请求时,非阻塞的read请求在数据没准备好的情况下立即返回,用户线程可以继续往下执行,此时应用程序不断地轮训内核,直到数据准备好且内核将数据拷贝到应用程序缓冲区后,read调用才可以获取结果。
- 注意最后一次read调用获取数据的过程,这是一个同步的过程,需要等待(同步指的是内核态的数据拷贝到用户程序的缓冲区这个过程)。
- 为了解决上述这种不断轮询的方式(应用程序每次轮询内核的IO是否准备好),于是就出现了IO多路复用的技术,如select、poll、epoll,它们是通过IO事件的分发,当内核的数据准备好时,再以事件通知应用程序进行操作。这个做法大大改善了应用进程对CPU的利用率,在没有被通知的情况下,应用进程可以使用CPU做其他的事情。
- 上图是使用IO多路复用的过程,使用read获取数据的过程,即数据从内核态拷贝到用户态这个过程是一个同步的过程,线程需要等待read系统调用返回数据。
同步与异步IO
无论是阻塞IO、非阻塞IO还是基于非阻塞的IO多路复用,它们都是同步的。
同步
在read调用从内核读取数据的时候,内核将数据从内核空间拷贝到用户空间的这个过程是需要等待的,这个过程是同步的。如果内核的拷贝效率不高,read调用就会在这个同步的过程中有一个较长的等待时间。
异步
内核将数据准备好和将数据从内核态拷贝到用户态,这两个过程都不用等待。函数aio_read实现这个功能。当用户进程发起aio_read调用后,进程立即返回,内核准备好数据后自动将数据从内核态拷贝到用户态,整个拷贝过程是内核自动完成的。与同步不同的是,应用程序不需要主动发起拷贝动作。