做人呢,最紧要就系开心啦

Linux内核之IO1: I/O模型

659次阅读
没有评论

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

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

Linux 内核之 IO1: I/ O 模型

Systemd readahead:

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

Linux 内核之 IO1: I/ O 模型

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

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

1 阻塞与非阻塞

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

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

Linux 内核之 IO1: I/ O 模型

Linux 内核之 IO1: I/ O 模型

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

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

(2)非阻塞

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

2 多路复用

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

(1) select

Linux 内核之 IO1: I/ O 模型

select()处理流程

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

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

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

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

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

(2)epoll()

Linux 内核之 IO1: I/ O 模型

epoll 与 select 的不同:

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

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

Linux 内核之 IO1: I/ O 模型

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

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

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

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

3 异步 IO

Linux 内核之 IO1: I/ O 模型

(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

Linux 内核之 IO1: I/ O 模型

模型对比:

Linux 内核之 IO1: I/ O 模型

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

正文完
 
admin
版权声明:本站原创文章,由 admin 2022-01-04发表,共计1354字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)