举例
网络中socket的一个read()是个一个IO操作命令,具体流程如下
应用程序调用read命令,通知内核读取数据
内核创建文件描述符
内核从物理层收到读指令,从网络中获取数据包
数据包传到TCP/IP层,解析数据包的头
内核将数据包缓存在文件描述符的读缓存区 这里的读缓存区是在内核中
当文件描述符读缓存区数据字节数大于应用程序定义的低水位的时候,此时文件描述符处于读就绪的状态
将读缓存区的数据复制到应用程序(用户区)返回
每个文件描述符都有自己的读缓存区和写缓存区,读缓存区对于read操作,写缓存区对应write操作
读缓存区和写缓冲区都是在内核中
现在Linux有5种IO模型
同步模型(synchronous IO)
- 阻塞IO(bloking IO)
- 非阻塞IO(non-blocking IO)
- 多路复用IO(multiplexing IO)
- 信号驱动式IO(signal-driven IO)
异步IO(asynchronous IO)
同步 synchronous :数据描述符缓存是由谁来进行读取的?由用户程序读取,则判断为同步;由内核推送,判断为异步
同步IO,需要用户进程主动将存放在内核缓冲区中的数据拷贝到用户进程中。
异步IO,内核会自动将数据从内核缓冲区拷贝到用户缓冲区,然后再通知用户。阻塞的意思就是说 用户现在的状态是是否在挂起,阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的 ,阻塞调用是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务。函数只有在得到结果之后才会返回。