IO(输入/输出)

用户态和内核态

用户态

用来运行应用程序,不能直接对操作系统进行调用,而是需要切换到内核态对操作系统进行操作。

内核态

直接访问操作系统资源或运行操作系统程序。

例如程序要保存一个文件到硬盘,在程序执行的用户态,是直接操作磁盘的。只有切换到内核态才能真正去操作磁盘。

内核态运行操作系统程序,操作硬件,用户态运行用户程序;

当程序运行在3级特权上时,可以称之为运行在用户态,当程序运行在0级特权级上时,称为运行在内核态。

R0 相当于内核态,R3 相当于用户态。

IO(Input/Output)

计算机角度的IO

输入设备:向计算机输入数据和信息的设备,键盘,鼠标都属于输入设备;

输出设备:用于接收计算机数据的输出显示,一般显示 器、打印机属于输出设备;

操作系统角度的IO

操作系统负责计算机的资源管理和进程的调度,经过操作系统,才能做一些特殊操作,如磁盘文件读写、内存的读写等。

真正的IO是在操作系统上执行的,即应用程序的IO操作:

IO调用:IO调用是由进程发起的

IO执行:是操作系统内核的工作

应用程序发起的一次 IO 操作包含两个阶段:

IO调用:应用程序进程需要向操作系统内核发起调用

IO执行:操作系统内核完成IO操作

IO模型

阻塞IO

定义:应用程序发起IO调用,但是内核的没有准备好,应用程序就会进入阻塞等待,等待内核数据准备好。必须等待内核数据准备好,程序才继续向下执行,效率低,浪费资源

经典应用:阻塞socket、Java BIO

缺点:如果内核数据一直没有准备好,那么用户线程将一直阻塞,浪费性能,,可以使用非阻塞IO优化。

非阻塞IO(NIO)

定义:如果内核数据还没准备好,可以先信息给用户线程,让它不需要等待,而是通过轮询的方式再来请求。

        当应用程序发起调用后,操作系统如果没有准备好数据,返回错误状态码,应用程序轮询再次发起调用,直到操作系统数据准备好了,将数据返回到用户内核空间。

非阻塞IO的流程:

  • 应用程序向操作系统内核发起recvfrom()读取请求
  • 操作系统内核数据没有准备好,立即返回回 EWOULDBLOCK 错误码
  • 应用程序进程轮询调用,继续向操作系统内核发起recvfrom读取请求
  • 操作系统你和数据准备好了,从内核缓冲区拷贝到用户空间
  • 完成调用,返回成功提示

recvfrom()用来接收远程主机经指定大的socket传来的数据,并把数据传到由参数buf指向的内存空空间。

优点:提高了性能,采用轮询。

缺点:频繁的轮询导致频繁的系统调用,消耗大量的CPU资源。考虑IO多路复用。

IO多路复用

定义:为了解决NIO的频繁轮询的问题,等待内核数据准备好了,主动通知应用程序去进行系统的调用。        

核心思想:系统为我们提供一类函数(select、poll、epoll),它们可以同时监控多个fd的操作,任何一个返回内核数据就绪,应用程序再发起recvform系统调用

文件描述符fd(File Descriptor),它是计算机科学中的一个术语,形式上是一个非负整数。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。

select

       应用程序发起一次调用之后,就由select()函数负责监听,应用程序不需要轮询,当有数据准备好了,那么就将数据向用户态返回。

好处:不同轮询。

缺点:监听的IO最大连接数有限,在Linux系统上一般为1024。需要遍历fdset,找到就绪的描述符fd。

poll

与select相同,但是解决了select连接数限制,但同样需要遍历

epoll

给每个监听的文件描述符(fd)绑定一个回调函数,当数据准备就绪后,触发回调函数处理。

优点:不需要遍历

总结select、poll、epoll 的区别

selectpollepoll
底层数据结构数组链表红黑树和双链表
获取就绪的fd遍历遍历事件回调
事件复杂度O(n)O(n)O(1)
最大连接数1024无限制无限制
fd数据拷贝每次调用select,需要将fd数据从用户空间拷贝到内核空间每次调用poll,需要将fd数据从用户空间拷贝到内核空间使用内存映射,不需要从用户空间频繁拷贝fd数据到内核空间

      epoll 明显优化了 IO 的执行效率,但在进程调用 epoll_wait()时,仍然可能被阻塞。能不能不用我老是去问你数据是否准备就绪,等我发出请求后,你数据准备好了通知我就行了,这就诞生了信号驱动 IO 模型。

IO 模型之信号驱动模型

信号驱动:当内核态数据准备好以后,内核态向用户态发送信息,用户态发起请求获取数据。

异步IO(AIO)

是真正的非阻塞IO,用户进程只需要发起一次调用,在内核态就会一次性直接将数据封装好,然后返回。

一个经典生活的例子:

BIO

小明去吃同仁四季的椰子鸡,就这样在那里排队,等了一小时,轮到她了,然后 才开始吃椰子鸡。

NIO

小红也去同仁四季的椰子鸡,她一看要等挺久的,于是去逛会商场,每次逛一下, 就跑回来看看,是不是轮到她了。于是最后她既购了物,又吃上椰子鸡了。

AIO

小华一样,去吃椰子鸡,由于他是高级会员,所以店长说,你去商场随便逛会吧, 等下有位置,我立马打电话给你。于是小华不用干巴巴坐着等,也不用每过一会儿就跑回来看有没有等到,最后也吃上了美味的椰子鸡

Java中的IO

BIO(阻塞IO)例如ServerSocket、Scanner等都是阻塞式的,效率低,可以通过线程独立运行,实现不阻塞。

NIO 非阻塞IO

非阻塞IO核心3的组件:通道(Channels)、缓存(Buffers)、选择器(Selectors核心)

通道读写数据是面向缓存区的

选择器可以监听多个通道,一旦某个通道有事件(读、写、链接)发生,都会被选择器捕捉。一个选择器可以监听多个通道,是非阻塞的,通过一个线程,就可以处理多个通道任务。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值