Java IO:操作系统的IO处理过程以及5种网络IO模型
2017-04-10 11:15
1176 查看
当我们需要理解关于 IO 的时候,最好还是理解操作系统是如何处理IO的。
操作系统如何处理IO
Linux 会把所有的外部设备都看成一个文件来操作,对外部设备的操作可以看成是对文件的操作。
我们对一个文件的读写,都会通过内核提供的系统调用,内核会给我们返回一个 File Descriptor,这个描述符是一个数字,指向内核的一个结构体,我们应用程序对文件的读写就是对描述符指向的结构体的读写。
系统调用是如何完成IO操作?
Linux 会把内存分为 内核区和用户区。Linux 的内核区会帮我们管理所有的硬件资源,并且会提供系统调用,我们应用程序的读操作,就会通过系统调用 read 发起一个读操作,这个时候,内核就会创建一个文件描述符,通过驱动向硬件发送读指令,并且把读的数据放在描述符指向的结构体的缓冲区中。当这个数据传到用户区的时候,就完成了一次 IO。
Linux 系统调用的 read,是一个阻塞函数。这个我们应用程序在发起read系统调用的时候,就必须要阻塞,进程挂起,等待文件描述符的读就绪。
从上面我们可以知道,应用程序的一个 read系统调用,需要经过:
1、硬件读取文件数据到文件描述符指向的结构体的缓冲区。
2、结构体的缓冲区的数据 传输到 用户区。
阻塞式 IO
在进行网络IO的时候,进程发起一个 recvform 系统调用,然后进程就会被阻塞,什么也不干,等待上述 所说的 1 和 2步骤完成(也就是硬件读取内容到内核的结构体缓冲区,结构体缓冲区的内容到用户区),最后进程再被处理。大致如下图:
非阻塞式 IO
在上述的 阻塞式 IO中,可以看到,进程在发起了 recvform 系统调用的时候,就会阻塞,那么非阻塞式 IO 和 阻塞式 IO 的一个区别就在这里,它并不会阻塞,而是马上返回一个错误码,进程在得到错误码之后,可以干点别的事情,然后再重复上述的步骤,也就是又发起一个 recvform 系统调用。这个过程就成为轮询。(注意,这是针对第一步)
IO 复用
由上面的非阻塞式IO可以看出,轮询占了很大一部分过程,这个过程会消耗很多CPU时间。这个轮询是由用户区发起的,但是,_这个轮询如果是由内核区发起的,那么效率就有提升。_IO复用提供了两个 系统调用 :select 和 poll。select 系统调用是内核级别的,它和 非阻塞式的轮询 有一个区别,就是select 轮询 可以等待多个 socket,任何一个socket 的数据准备好了,那么就可以返回进行读。 select 和 poll调用之后,会阻塞进程,那么这种阻塞进程不同于 第一种 阻塞式IO的阻塞,此时的select不是等到socket数据全部到达后再处理,而是有一部分数据就会调用用户进程处理。
打个比方:钓鱼的时候,雇佣一个帮手,他可以同时抛下多个鱼竿,任何一杆的鱼上钩,他就会拉杆,他只负责帮我们,不负责帮我们处理,所有我们还得在一边等着,等到他拉杆,我们再处理。 如下图:
Ps:实际上 select/poll 是落后的,因为 select 的句柄数有限,为1024 个,也就是说,同次检测 1025 个句柄死 是不可能。另外,内核的select是采用轮询的方法,select检测的句柄数越大就会越耗时,这些都是问题。那么epoll就能够解决这些问题,epoll 实际上也是 select/poll 的增强版。
信号驱动式IO
也就是说,数据未准备就绪的时候,那么就进行等待,但是这个等待不会进行轮询,也不会阻塞。而是在某一时刻如果数据准备好了,那么内核会通知进程启动IO操作,将数据从内核区复制到用户区。如下图4 所示:
异步 IO
异步 IO 是指 相当于 信号式驱动 IO 的一个升级版本。异步 IO 是等 内核完成整个操作之后再通过应用程序,这整个过程包括了 硬件读取数据到 内核结构体的缓冲区中,以及缓冲区的数据复制到 用户区中,这整个过程进程都不会阻塞。如下图:
总结:
以上就是 操作系统如何处理IO,以及常用的 5种 网络 IO模型。包括(阻塞式IO(java的传统IO),非阻塞式IO(NIO),多路复用IO,信号驱动IO,异步IO)。
操作系统如何处理IO
Linux 会把所有的外部设备都看成一个文件来操作,对外部设备的操作可以看成是对文件的操作。
我们对一个文件的读写,都会通过内核提供的系统调用,内核会给我们返回一个 File Descriptor,这个描述符是一个数字,指向内核的一个结构体,我们应用程序对文件的读写就是对描述符指向的结构体的读写。
系统调用是如何完成IO操作?
Linux 会把内存分为 内核区和用户区。Linux 的内核区会帮我们管理所有的硬件资源,并且会提供系统调用,我们应用程序的读操作,就会通过系统调用 read 发起一个读操作,这个时候,内核就会创建一个文件描述符,通过驱动向硬件发送读指令,并且把读的数据放在描述符指向的结构体的缓冲区中。当这个数据传到用户区的时候,就完成了一次 IO。
Linux 系统调用的 read,是一个阻塞函数。这个我们应用程序在发起read系统调用的时候,就必须要阻塞,进程挂起,等待文件描述符的读就绪。
从上面我们可以知道,应用程序的一个 read系统调用,需要经过:
1、硬件读取文件数据到文件描述符指向的结构体的缓冲区。
2、结构体的缓冲区的数据 传输到 用户区。
阻塞式 IO
在进行网络IO的时候,进程发起一个 recvform 系统调用,然后进程就会被阻塞,什么也不干,等待上述 所说的 1 和 2步骤完成(也就是硬件读取内容到内核的结构体缓冲区,结构体缓冲区的内容到用户区),最后进程再被处理。大致如下图:
非阻塞式 IO
在上述的 阻塞式 IO中,可以看到,进程在发起了 recvform 系统调用的时候,就会阻塞,那么非阻塞式 IO 和 阻塞式 IO 的一个区别就在这里,它并不会阻塞,而是马上返回一个错误码,进程在得到错误码之后,可以干点别的事情,然后再重复上述的步骤,也就是又发起一个 recvform 系统调用。这个过程就成为轮询。(注意,这是针对第一步)
IO 复用
由上面的非阻塞式IO可以看出,轮询占了很大一部分过程,这个过程会消耗很多CPU时间。这个轮询是由用户区发起的,但是,_这个轮询如果是由内核区发起的,那么效率就有提升。_IO复用提供了两个 系统调用 :select 和 poll。select 系统调用是内核级别的,它和 非阻塞式的轮询 有一个区别,就是select 轮询 可以等待多个 socket,任何一个socket 的数据准备好了,那么就可以返回进行读。 select 和 poll调用之后,会阻塞进程,那么这种阻塞进程不同于 第一种 阻塞式IO的阻塞,此时的select不是等到socket数据全部到达后再处理,而是有一部分数据就会调用用户进程处理。
打个比方:钓鱼的时候,雇佣一个帮手,他可以同时抛下多个鱼竿,任何一杆的鱼上钩,他就会拉杆,他只负责帮我们,不负责帮我们处理,所有我们还得在一边等着,等到他拉杆,我们再处理。 如下图:
Ps:实际上 select/poll 是落后的,因为 select 的句柄数有限,为1024 个,也就是说,同次检测 1025 个句柄死 是不可能。另外,内核的select是采用轮询的方法,select检测的句柄数越大就会越耗时,这些都是问题。那么epoll就能够解决这些问题,epoll 实际上也是 select/poll 的增强版。
信号驱动式IO
也就是说,数据未准备就绪的时候,那么就进行等待,但是这个等待不会进行轮询,也不会阻塞。而是在某一时刻如果数据准备好了,那么内核会通知进程启动IO操作,将数据从内核区复制到用户区。如下图4 所示:
异步 IO
异步 IO 是指 相当于 信号式驱动 IO 的一个升级版本。异步 IO 是等 内核完成整个操作之后再通过应用程序,这整个过程包括了 硬件读取数据到 内核结构体的缓冲区中,以及缓冲区的数据复制到 用户区中,这整个过程进程都不会阻塞。如下图:
总结:
以上就是 操作系统如何处理IO,以及常用的 5种 网络 IO模型。包括(阻塞式IO(java的传统IO),非阻塞式IO(NIO),多路复用IO,信号驱动IO,异步IO)。
相关文章推荐
- 网络io模型&java nio
- I/O模型和原理,以及简单解析客户端请求WEB服务器内部处理过程,MPM三种模
- 【转载】5种网络IO模型
- 只使用处理IO的printDigit函数,编写一个过程以输出任意实数可以为负(java数据结构与算法习题1.3)
- 网络IO工作模型以及在分布式中的应用
- 【Java】【系统状态】获取系统信息(包括操作系统、jvm、cpu、内存、硬盘、网络、io等)
- linux下5种网络IO模型简介
- [置顶] 【java I/O模型】 Java 网络IO编程总结
- 网络访问过程中遇到的java.io.IOException: Target host must not be null的问题
- 5种网络IO模型(有图,很清楚)
- Java网络编程 - 非阻塞IO模型
- IO的阻塞与非阻塞、同步与异步以及Java网络IO交互方式(转)
- Java 网络 IO 模型
- 网络编程中的5种IO模型
- [JAVA修炼之路四]-JVM内存模型以及对象实例化过程
- java网络编程(一):java传统的阻塞IO以及多线程解决方案
- 【Java】【系统状态】获取系统信息(包括操作系统、jvm、cpu、内存、硬盘、网络、io等)
- Java 网络处理(net io URL 等)
- Java的对象序列化以及文件IO处理
- Java IO:网络IO模型