1、I/O总述
1.1、I/O在系统层面发生的过程和性能评级
一次I/O的过程大体可以分为从磁盘读取本地数据,或者从网络端口读取远程数据,这两种I/O发生的过程类似,将数据流向作为分析的视角,第一种本地I/O的过程可以理解成,数据从磁盘被加载进内核态缓冲区,再被拷贝至用户态缓冲区;第二种远程I/O的过程和第一种本地I/O过程类似,唯一的区别是数据不再是从磁盘加载进内核缓冲区,而是从网络端口加载进内核缓冲区,如果是网络I/O,数据还需被拷贝至Socket缓冲区,其中除了用户态缓冲区在用户态,内核态缓冲区和Socket自身持有的缓冲区都是在内核态。
上面的总述比较抽象,下面选择网络I/O具体分析。
1)读取:read
当一个Socket(A)被创建完成后,会监听一个端口,此时另一台远程的机器或者本地的另一个进程通过另一个Socket(B)和A完成连接后,Socket A会顺势调用read()函数,获取Socket B发来的数据,调用read()函数后,持有Socket A的线程(或进程,方便起见,之后一律使用线程来实现)会首先判断该Socket的用户态缓冲区是否有数据,如果有数据会直接返回继续执行,若没有数据,该线程会被阻塞并触发sys_read这个系统调用,此时该线程所占用的CPU会进入内核态,CPU会将其他端口传来的数据加载至内核缓冲区(Linux 中,同一台机器中的不同线程通过Socket实现进程间通信是不会通过网卡的),加载完以后,会再讲数据拷贝至用户态缓冲区,也就是该Socket本身持有的缓冲区,拷贝完成以后,该线程才能继续执行下去。
2)发送:write
1)中分析了线程读取一次数据的过程,其中发生阻塞的原因是数据从内核态至用户态的拷贝需要时间,发送的过程和读取类似,不同的是,阻塞判断的条件是内核态的缓冲区是否为空,而