ITPub博客

首页 > 数据库 > 数据库开发技术 > 做个家务,让我搞懂了 Linux I/O 模型

做个家务,让我搞懂了 Linux I/O 模型

原创 数据库开发技术 作者:咸鱼运维杂谈 时间:2022-12-12 20:00:00 0 删除 编辑

I/O 其实就是 input 和 output(输入输出)


在计算机操作系统中对应数据流的输入与输出,在 Linux 中,既有文件的 I/O,也有网络 I/O


无论是文件 I/O 还是网络 I/O,其传输过程都是类似的


今天我们以文件 I/O 为例,来深入浅出一下 Linux 的 I/O 模型


我们的程序想要打开一个文件,去查看里面的内容,那么就需要将文件内容加载到内存里面,这个过程是一个比较复杂的过程


首先需要通过内核将数据从硬盘中读取出来,然后放到操作系统的内核缓冲区中,然后再将数据拷贝到程序缓冲区,这时候程序才能获取到相应的数据,打开相应的文件


简单来说,无论什么 I/O 模型,其读取过程都会经历下面两个阶段:

  • 将数据放到内核缓冲区(等待数据过程)

  • 将内核缓冲区的数据拷贝(copy)到程序缓冲区(拷贝数据过程)



上面两个阶段完成之后,进程才能够对数据进行操作(读 or 写)


为了让大家能够更好的理解 Linux I/O 模型,咸鱼用囤了一个星期的臭衣服来作为例子(主要是懒)


一个轻松惬意的周六下午,咸鱼看着满满一篮子的臭衣服,痛定思痛,决定今天一定要把这堆衣服洗了


但是咸鱼家的洗衣机比较老旧,别人家的洗衣机都是洗涤甩干一条龙的,咸鱼家的洗衣机只能先洗涤,等洗涤完毕后咸鱼再去按甩干按钮进行衣服甩干(太惨了)


那么就将洗衣服可以分为两个阶段:

  • 按下洗涤按钮,洗衣机对衣服进行洗涤

  • 按下甩干按钮,洗衣机对衣服进行甩干


以上两个阶段均完成了之后,咸鱼才能把衣服拿去晾晒


阻塞 I/O

咸鱼在按下了洗衣机的洗涤按钮之后,就拿个小板凳在旁边干等着,在洗涤完衣服之前咸鱼啥事都不能干,只能乖乖地等洗衣机洗涤衣服


当洗衣机洗完衣服之后,咸鱼就按下甩干按钮,然后依旧坐在小板凳上干等着,直到洗衣机甩干好衣服为止


以上这两个阶段(洗涤和甩干阶段),咸鱼都处在一个阻塞的状态,他啥也干不了,只能乖乖地等洗衣机工作完


总结:

在阻塞 I/O 模型里面,将数据放到内核缓冲区(等待数据过程)以及将内核缓冲区的数据拷贝(copy)到程序缓冲区(拷贝数据过程),进程都是阻塞的



非阻塞 I/O

跟第一次不一样的是,咸鱼按下了洗衣机的洗涤按钮之后,就不断地去打开洗衣机的盖子,去看衣服洗好了没有


等洗衣机洗好了衣服之后,咸鱼按下洗衣机的甩干按钮,然后坐在小板凳上干等着,直到洗衣机甩干好衣服为止


以上这两个阶段(洗涤和甩干阶段),咸鱼都处在一个阻塞的状态,他啥也干不了,但是在第一阶段(洗涤阶段),他并没有干等着,而是不断地去查看洗衣机的状态——是否洗好衣服了


总结:

在非阻塞 I/O 模型里面,将数据放到内核缓冲区(等待数据过程)以及将内核缓冲区的数据拷贝(copy)到程序缓冲区(拷贝数据过程),都是阻塞的。


但比阻塞 I/O 有进步了一点,进程并不是站在那里干等,而是时不时跑去问一下内核。即使是无用功,效率多少还是提高了一点的


I/O 复用

这一天,邻居家里有事外出了,但邻居也在洗衣服,于是邻居就拜托咸鱼帮忙看一下洗衣机


邻居家的洗衣机跟咸鱼家的洗衣机一样老旧,同样需要先洗涤后甩干


这个时候咸鱼就需要去不断地来回跑,先去看看自己家的洗衣机洗好衣服了没,然后再去看看邻居家洗衣机洗好衣服了没,接着再去看看自己家洗衣机洗好衣服了没


循环往复,直到看到某一台洗衣机完成洗涤


当咸鱼看到某一台洗衣机完成洗涤之后,就需要按下甩干按钮然后乖乖等衣服甩干


在洗涤阶段里面,咸鱼会不断地对洗衣机进行轮询查看,但依旧是阻塞的,因为咸鱼干不了其他事


在甩干阶段里,也是堵塞的,咸鱼只能乖乖地等洗衣机将衣服甩干


总结:


I/O复用模型的第二阶段与阻塞 I/O、非阻塞 I/O 的第二阶段是一致的(进程是堵塞的只能乖乖地将数据从内核缓冲区 copy 到程序缓冲区)


但是在第一阶段中,进程能够同时轮询多个数据流,监听多个数据流,其效率有巨大的提升


信号驱动 I/O

咸鱼发现,在小板凳上干等着多浪费时间啊,俗话说浪费时间无异于自杀,咸鱼决定在洗衣机洗涤阶段去干其他家务活,当洗衣机洗涤完毕后,会发出滴滴的声音,咸鱼听到这个声音之后就回来对衣服甩干


于是在洗涤阶段,咸鱼再也不用坐在小板凳上干等着,而是去拖地、烧水(干其他事)


当洗衣机洗涤完毕后,发出滴滴声音(信号),咸鱼听到这个声音之后就回来然后对衣服进行甩干


但是在甩干阶段咸鱼还是需要坐在小板凳上乖乖地等着


总结:

虽然说信号驱动 I/O 模型的第二阶段跟前面三个 I/O 模型一样,即进程是阻塞的。但在第一阶段做到了真正的异步


信号驱动 IO 在第一阶段,进程去请求内核读取数据,这时候其不会阻塞,也不会去轮询,而是设置一个信号回调。 当数据完全拷贝到系统内核时,系统发出 SIGIO 信号,通知进程去进行第二阶段,将数据拷贝到程序缓冲区


异步 I/O

聪明的咸鱼再次发现,既然我在洗涤阶段可以去干其他事,当我听到洗衣机洗涤完毕发出的滴滴声时我再回来进行甩干


那我为什么不能在甩干阶段也去干其他事情呢,当衣服甩干之后,洗衣机发出嘟嘟声,我听到嘟嘟声就知道甩干完毕了


于是在洗涤阶段和甩干阶段,咸鱼都不需要坐在小板凳上干等着,而是去干别的事情,当洗涤完毕或者甩干完毕的时候,洗衣机会发出滴滴或嘟嘟的声音


咸鱼听到声音就知道洗衣机洗涤或甩干完毕了,这时候他再过来处理衣服就行了


总结:

与信号驱动 I/O 类似,异步 I/O 模型在第一阶段通过信号回调的方式实现了进程的非阻塞


而在第二阶段,进程将数据从内核缓冲区 copy 到程序缓冲区的时候并非阻塞,而是同样设置一个信号回调,当 copy 完成后,进程收到通知,再去执行相应的操作


异步 IO 不仅仅是在第一阶段实现了信号回调,其也在第二阶段实现了信号回调,从而完全实现了异步 IO 操作

原文作者:咸鱼运维杂谈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
最新的技术文章首先发布在微信公众号:咸鱼运维杂谈 擅长Linux系统维护、开源软件维护、自动化运维等领域,博客主要偏向于学习笔记及经历分享

注册时间:2021-05-29

  • 博文量
    193
  • 访问量
    84254