高并发IO的底层原理
1.1,IO读写的基本原理
为了避免用户进程直接操作系统内核,保证内核安全。操作系统将内存(虚拟内存)分为:内核空间和用户空间:
内核空间–>内核态
用户空间–>用户态
用户态进程不能直接操作内核资源,必须通过系统调用(System call)向内核发送指令,完成系统资源调用。
用户进程进行IO读写依赖于底层的IO读写,基本会用底层的read和write两大系统调用。
从物理设备到应用内存之间是通过缓冲区完成数据的IO操作。
1.1.1,内核缓冲区和进程缓冲区
计算机的外部物理设备与内存和CPU相比,有非常大差距,所有需要缓冲区实现数据交换。
操作系统内核只有一个内核缓冲区,–>内核缓冲区。
每个用户程序(进程)都有自己独立的缓冲区 --> 用户缓冲区。
Linux系统中用户程序IO读写程序并没有实际的IO操作,是通过用户缓冲区和内核缓冲区之间直接进程数据交换实现的。
1.2,四种主要的IO模型
常见的IO模型有四种:(面试常问)
1,同步阻塞IO -->BIO
阻塞IO:需要内核IO操作彻底完成后才能返回到用户空间执行用户程序的操作指令。Java中默认创建的socket都属于阻塞IO模型。
同步和异步可以看成发起IO请求的两种方式:
同步:用户进程主动发起IO请求,系统内核是被动接收。
异步:系统内核主动发起IO请求,用户空间是被动接收。
同步阻塞IO(BIO):指用户空间(或线程)主动发起,需要等待内核IO操作彻底完成后才返回到用户空间的IO操作。在IO操作过程中,发起IO请求的用户进程处于阻塞状态。
2,同步非阻塞IO --> NIO
非阻塞IO(Non-Blocking IO,NIO):指用户空间程序不用等待内核IO操作彻底完成,即可返回用户空间执行后续的指令。发起IO请求的用户进程处于非阻塞状态。同时,内核会立即返回给用户一个IO状态值。
阻塞和非阻塞的区别:
阻塞是指用户进程一直等待,不能做其他事情。
非阻塞是指用户进程获得内核返回的状态值就返回自己的空间,去执行后续指令。
注:这里不是JAVA中的NIO,java编程中的NIO是IO多路复用模型。
同步非阻塞IO(NIO):用户进程主动发起,不需要等待内核IO操作彻底完成可立即返回到用户空间的IO操作。用户进程处于非阻塞状态。
3,IO多路复用
用于查询IO文件描述符(含socket连接)的就绪状态。在Linux系统中,新的系统调用为select/epoll 。
一个用户线程可以监视多个文件描述符,一旦某个文件描述符就绪(一般是内核缓冲区可读/可写),内核就能够将文件描述符的就绪状态返回给用户进程,用户空间可以根据文件描述符的就绪状态进行相应的IO系统调用。
IO多路复用,也称为异步阻塞IO。
4,异步非阻塞IO
异步IO(AIO):指用户空间的线程变成被动接收者,而内核空间成为主动调用者。
异步IO类似于Java中典型的回调模式。通常依靠事件,回调等机制来通知调用者其返回结果