Linux内核之IO1: I/O模型

在业务执行过程中,常伴随大量的IO操作,如果IO操作和CPU消耗不能合理安排,将会导致整体业务执行效率低下,用户体验极差。

比如手机启动过程,有大量CPU消耗和IO操作。用Bootchart记录android启动过程的CPU/IO消耗如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCRAFC0H-1598518385439)(media/ea040143e464284eac5cb90a25bfd1bf.png)]

Systemd readahead:

Systemd readahead-collect.service搜集系统启动过程中的文件访问信息,Systemd
readahead-replay.service在后续启动过程中完成回放,即将IO操作与CPU并行;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B8dw2J9U-1598518385442)(media/d9ba7003dd852f0decde1a1cdcfe5dcc.png)]

提高效率的一个宗旨,把CPU和IO的交替等,变为CPU和IO操作(不需要CPU参与)同时工作,充分利用系统资源;

为解决CPU/IO并行问题,Linux提供了很多IO模型;

1 阻塞与非阻塞

(1)阻塞: 一般来说,进程阻塞,等待IO条件满足才返回;

有个例外,阻塞可以被信号打断;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SaakZk1k-1598518385444)(media/4d498cafcd020df899348b4519839b08.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cZxcQYRX-1598518385447)(media/1a979568086be61aa25ca12637799b45.png)]

若设置信号标记,act.sa_flags |= SA_RESTART;
接收信号,read阻塞不返回,但是信号响应函数还是会调用;相当于系统自动重新进入阻塞;

用signal()函数设置信号,其调用sigaction自动设置SA_RESTART;

(2)非阻塞

read/write等IO调用,IO设备没就绪,立即返回,实际工程上用的不多;

2 多路复用

实际业务中,一般有多个IO请求,每个请求响应都用简单的阻塞模型效率太低,Linux提供了多路复用的的系统调用:

(1) select

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aFU8Z5wY-1598518385449)(media/05795b93e54068292258c24ee1ba4297.png)]

select()处理流程

a.告诉系统,要关注哪些IO请求;

b.阻塞等待,直到有IO就绪,select返回;

c.主动查询是哪个IO就绪,然后响应该IO;

d.重新关注新的IO请求;

当IO请求过多时,这种查询的方式也很浪费资源,因此Linux提供了一个新的系统调用

(2)epoll()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HPDMjVDm-1598518385450)(media/37054435ff7dd066a54e129d6e874b81.png)]

epoll与select的不同:

a.将注册IO请求和等待事件触发分离开;

b.返回后,直接告诉哪些IO就绪,不用再主动查询

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4mtLiUhS-1598518385451)(media/38b1aa64e1aa525a85ea753c778aa946.png)]

当IO数量不多时,可以用select或epoll,但当IO非常多时,比如大型网络应用,响应多个IO请求时,用epoll效率远高于select。

signal io方式,都是read/write阻塞,底层实现,待IO就绪后,内核发送信号,唤醒阻塞;

比如读触摸屏应用,read被阻塞,只有触摸屏被按下,触发中断程序响应,读取触摸屏行为数据后,内核发送信号唤醒APP的等待,APP读到触摸动作信息,做相应业务处理。

目前工程上,处理异步I/O更多用以下方法

3 异步IO

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yXCC2kR4-1598518385452)(media/b2d5d1eeb9d0aab9efd3d5ccc3747be1.png)]

(1) C库提供的Glibc-AIO

Glibc-AIO原理,aio_read()立即返回,后台自动创建线程读取io,aio_suspend()查询IO是否完成,完成立即返回,未完成,等待;

(2) 内核提供的Kernel-AIO:

一般用来读取硬盘数据,比如数据库读取;

这些异步模型,天然的将IO与CPU消耗等待做并行处理;

4 Libevent事件触发

功能类似QT/VC的按钮,注册回调函数,当事件触发时,执行回调函数。

libevent是一个跨平台库,封装底层平台调用,提供统一API。Windows/Solaris/linux。

gcc xxx.c -levent

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tBCiKYlP-1598518385453)(media/cad42f145a09664cb6b045a2b6ed999a.png)]

模型对比:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Qo2g9Lu-1598518385454)(media/78e1876b15c0cc8ee39a71105aec58e8.png)]

C10K问题:http://www.kegel.com/c10k.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值