Linux Block 层在 Linux 内核设计之初就作为几大子系统存在,当然这也是得益于他的前辈 Unix 等优秀的设计。作为 IO 子系统的中间层,他为上层输出接口,为下层提供数据,像个勤劳的小蜜蜂,本文介绍通用块层中的最具传奇色彩的 bio,他就像是一个原子,是在整个 block 层的最小单位,不可分割。

bio 的组成

作为最小单位以及传输介质,那么具体应该长得如何?他又承载着那些信息?

struct bio {

struct bio *bi_next; /* request queue link */

struct block_device *bi_bdev;

unsigned int bi_flags; /* status, command, etc */

int bi_error;

unsigned long bi_rw; /* 末尾 bit 表示 READ/WRITE,

* 起始 bit 表示优先级

*/

struct bvec_iter bi_iter;

/* 当完成物理地址合并之后剩余的段的数量 */

unsigned int bi_phys_segments;

/*

* To keep track of the max segment size, we account for the

* sizes of the first and last mergeable segments in this bio.

*/

unsigned int bi_seg_front_size;

unsigned int bi_seg_back_size;

/* 关联 bio 的数量 */

atomic_t __bi_remaining;

bio_end_io_t *bi_end_io;

void *bi_private;

unsigned short bi_vcnt; /* how many bio_vec's */

/*

* Everything starting with bi_max_vecs will be preserved by bio_reset()

*/

unsigned short bi_max_vecs; /* max bvl_vecs we can hold */

/* 当前 bio 的引用计数,当该数据为 0 时才可以 free */

atomic_t __bi_cnt; /* pin count */

struct bio_vec *bi_io_vec; /* the actual vec list */

struct bio_set *bi_pool;

/*

* We can inline a number of vecs at the end of the bio, to avoid

* double allocations for a small number of bio_vecs. This member

* MUST obviously be kept at the very end of the bio.

* 表示跟在 bio 后面的数据集合

*/

struct bio_vec bi_inline_vecs[0];

};

bio 结构体包含了大量的基础信息,这些都是一个基本单元的属性,他们代表着当前这个 bio 的状态,比如是读还是写或者是一些特殊的操作命令等,在 bio 的尾部携带了一个 bi_inline_vecs 数组1,这就是一个 bio 数据所在部分,相当于这个结构体描述的都只是元数据部分,实际数据都包含在紧跟其后的 bio_vec 中,那么这个 bio_vec 何许人也?

最小数据单位 bio_vec

struct bio_vec {

struct page *bv_page;

unsigned int bv_len;

unsigned int bv_offset;

};

顾名思义,bio_vec 就是一个 bio 的数据容器,专门用来保存 bio 的数据,当然他是这个 bio 大集体的一个最小项,刚刚说了 bio 是通用块层的最小集,而这个 bio_vec 则是组成 bio 数据的最小单位,他包含了一块数据所在的页,这块数据所在的页内偏移以及长度,通过这些信息就可以很清晰的描述数据具体位于什么位置,通过对这些数据的整合,可以将他们添加到 SGL(散列表) 中直接发送给后端硬件设备。

迭代器 bvec_iter

寻遍整个 bio 发现居然没有携带需要下盘的扇区编号以及当前 bio 的大小,这个很尴尬,但确实如此,相当于 bio 作为一辆汽车,他携带了货物但是没告诉他目的地这不是完蛋了吗?不是,真正的目的地保存在这个 bvec_iter 中,作为一个迭代器,自然他的使命就是用来遍历 bvec,也就是 bio 数据区。那么他好比就是这辆 bio 汽车的货物分拣员,自然我的目的地不必贴到车上,直接告诉分拣员也是可以的,因为后面的事情可不是这辆汽车再做,而是分拣员需要逐个卸货的时候用。一起来看看迭代器长什么样?

struct bvec_iter {

sector_t bi_sector; /* device address in 512 byte sectors */

unsigned int bi_size; /* residual I/O count */

unsigned int bi_idx; /* current index into bvl_vec */

unsigned int bi_bvec_done; /* number of bytes completed in current bvec */

};

bio 的逻辑架构图

关于 bi_io_vec 和 bi_inline_vecs 的关系

细心的朋友会发现,一个 bio 会有两个字段用来描述 bio 携带的数据,对于没有深入了解的人来讲会比较困惑,其实也比较容易理解,bio 结构在申请内存的时候会多申请 4 个 bvec 的位置跟随 bio 结构体上,这就是 bi_inline_vecs ,他是用来存放内联数据(不能太多,因为申请了不用就会造成内存浪费),当往该 bio 注入数据时,小块的 bio 会直接使用这个内联的数据区域保存小于 4 个 bvec 的信息,而无需重新调用 kmalloc 申请内存,减少了一次内存申请操作,牺牲一小部分内存达到对小 bio 的加速(内存申请过程很长且相对较慢),然后为了兼容后端的其他接口,会直接将 bi_io_vec 指针直接指向 bi_inline_vecs 所在的位置,目的就是告诉后端,数据存放在 bi_inline_vecs 位置上。如果超过 4 个以上的 bvec 才足够完整描述本次 IO 的全部数据,那么 bi_inline_vecs 字段是被直接忽略的,尽管他内存很早就申请好了,但是并不会被采用,而是需要重新自内存管理单元重新申请足额的内存保存这一次的 IO 数据,这就是前面说的一点点的内存浪费的原因。

bio和bieos哪个标注模式好_通用块层bio详解相关推荐

  1. bio和bieos哪个标注模式好_阿里巴巴和亚马逊电商模式差异?哪个电商好做

    我做跨境电商也有六年的时间了,在电商这个行业也有自己的一些经验.经验也许没有其他大卖家丰富,但会将我知道的都进行分享.如果有不懂得亚马逊问题可以+我(V:772024802).我这里给大家安排一堂直播 ...

  2. linux bio 描述一段内存,Linux 通用块层 bio 详解

    Linux Block 层在 Linux 内核设计之初就作为几大子系统存在,当然这也是得益于他的前辈 Unix 等优秀的设计.作为 IO 子系统的中间层,他为上层输出接口,为下层提供数据,像个勤劳的小 ...

  3. bio和bieos哪个标注模式好_2021秋招-NLP基础任务模型-NER

    NLP基础任务模型-NER 注: 基本全是转载,也都附加了转载链接,侵删. 多谢各位大佬的总结. 目录: 任务定义 简单综述 数据集细节总结 模型细节总结 损失函数计算 总结 NLP实战-中文命名实体 ...

  4. 数学建模_随机森林分类模型详解Python代码

    数学建模_随机森林分类模型详解Python代码 随机森林需要调整的参数有: (1) 决策树的个数 (2) 特征属性的个数 (3) 递归次数(即决策树的深度)''' from numpy import ...

  5. 数据库系统之:三级模式-两层映射详解

    数据库系统之:三级模式-两层映射详解 前言 一.数据库三大模式详解 1.外模式(反映了数据库系统的用户观) 2.概念模式(反映了数据库系统的整体观) 3.内模式(反映了数据库系统的存储观) 4.概念模 ...

  6. Python中下划线 _ 的最全用法详解

    Python中下划线 _ 的最全用法详解 '_'是什么? _在python中可以作为一个标识符,用于定义变量和方法唯一名称.同时它也是Python中的一个软关键字,指在某些特定上下文中保留的关键字.截 ...

  7. CSharp(C#)语言_委托和事件区别详解

    委托和事件区别详解 委托和事件的概念 委托 事件 委托和事件的作用 委托 事件 委托和事件的区别 委托和事件的详细解答请看C#系列文章 委托和事件代码实践 委托 事件 总结 委托和事件的概念 委托   ...

  8. java 值对象_java 中设计模式(值对象)的实例详解

    java 中设计模式(值对象)的实例详解 应用场景:在Java开发时,需要来回交换大量的数据,比如要为方法传入参数,也要获取方法的返回值,该如何能更好的进行数据的交互?这个时候就需要用到我们的值对象设 ...

  9. 04_Flink-HA高可用、Standalone集群模式、Flink-Standalone集群重要参数详解、集群节点重启及扩容、启动组件、Flink on Yarn、启动命令等

    1.4.Flink集群安装部署standalone+yarn 1.4.1.Standalone集群模式 1.4.2.Flink-Standalone集群重要参数详解 1.4.3.集群节点重启及扩容 1 ...

  10. (转载) Linux IO模式及 select、poll、epoll详解

    注:本文是对众多博客的学习和总结,可能存在理解错误.请带着怀疑的眼光,同时如果有错误希望能指出. 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案 ...

最新文章

  1. 讲解AI三大方向的模型与算法!
  2. 一个流畅的iOS图表框架PNChart
  3. 腾讯2017年第三季度财报:微信广告收入大幅增长
  4. sys no attribute argv
  5. vim进阶之202007命令记录
  6. express中get和post的区别
  7. POJ 3667 Hotel 线段树区间合并
  8. 软件工程概论第二周 开课作业
  9. can使能上拉 gpio_单片机GPIO输入电压不可过大,最好使能上拉
  10. fpga烧写bin文件_S3C2440移植uboot之编译烧写uboot
  11. Docker容器kali镜像导出/导入
  12. 全网首发:GB18030中,蒙文的错误
  13. vasp能装在window系统里吗_vasp 5.4.4 在win10/Ubuntu 18.04上的安装
  14. 能源在线监测管理系统
  15. python控制屏幕亮度_使用Python脚本更改显示器亮度
  16. 自己动手实现@Autowired注解
  17. 怎么把做好的ps保存成图片_PS保存图片提示“无法完成请求”,这里有4种解决方法...
  18. 一年365天,把1.0作为每天的能力值基础,每天原地踏步 则能力值为1.0,如果每天努力一点点则能力值提高1%,每天再努力一点则能力值提高2%,那一年后,这3种行为收获的成果相差多少呢?
  19. 微信公众号,主要分析哪些方面的数据?
  20. 游戏直播平台新赛程:负重前行与危中求生

热门文章

  1. 14.企业应用架构模式 --- Web表现模式
  2. 7.UNIX 环境高级编程--进程环境
  3. 35. systemtap
  4. linux登录闪回登录界面,两种闪回查询的使用实验
  5. opencv java 特征提取_OPENCV特征点java提取与匹配与比较
  6. LoadRunner9 5新特性
  7. 如何让你产品的用户拥有一流的上传体验
  8. vi 编辑器基本命令
  9. 【转】git使用教程
  10. Java中的for循环和JavaScript中的for循环差别初探(02)