当前课程知识点:Linux 内核分析与应用 > 第9章 设备驱动 > 9.8 工程实践-块设备驱动程序分析(中) > Video
大家好 我们在上一次节目中给大家留了一个思考题
这个思考题是这样的
在用户空间里面
比如说我们有一个数据buffer
这个数据buffer我们
怎么去通过write这个函数写入到这个
eMMC的这个存储空间里面
你比如说我在
用户空间使用open函数来
打开
data目录下面的一个
test的这么一个文件
然后调用write函数
把这个data的buffer
写入到这个文件里面
那我们的问题是说
这个write函数啊
它经历过Linux内核里面
什么样的内核模块以及经历过些什么样的数据结构
它才能把这个data的数据
写入到这个eMMC里面的这个sector里面
我在大概几年前
画过这样一个流程图
那我在这里简单给大家介绍一下这里的
一个过程
首先我们调用write这个函数
往这个句柄里面写数据的时候那么在内核空间里面它首先要
会通过打开的句柄
fd在内核里面找到它的
file的这样一个数据结构
那么在file数据结构里面他找到他的page cache
如果没找到page cache的话
那么他会新创建一个page cache
你要把这些page cache加到
内核管理page cache这种基数树里面
那么第二步它会根据这个
buffer的大小
然后去分配这个
buffer_head
这个buffer_head
然后通常是四个buffer_head
指向一个page
然后接下来非常重要的一步是
通过
文件系统的这个Get_block这个API
为这个page cache
去查找在磁盘中对应的是这个
block的号因为
通常文件系统会去管理说
这个数据它要存放在磁盘的哪个号里面哪个
block的号里面
然后接下来他要把数据
拷贝到这个page cache里面
那么这里直接调用这个
copy_from_user拷贝就可以了
然后接下来一步是把这个
buffer_head
和这个page cache都要设成Dirty就是说
这个page cache它是脏的页面
而且要把这个
文件所对应的inode
也要添加到系统里面的有一个
脏的这个队列里面
这是第一步
那么这一步完成了之后从
用空间的角度来看
这个write函数已经返回了
但是我们要注意到
这个步骤完成之后其实数据
并没有真正写入到eMMC里面
而是写入到
系统的缓存或者叫页缓存叫做page cache里面
那接下来第二步那么第二步说
Linux内核里面有一个叫做flush的这个内核线程
那么这个内核线程的主要的一个工作是说定期把一些
脏的page cache
写回到磁盘里面
这是这个flush内核线程的一个
主要的工作
那这个flush线程它会从刚才讲的一个
inode的这个Dirty队列里面去
去处理一个inode就是脏的一个inode
它会调用文件系统的write pages这种接口
去处理这个page cache
你比如说他首先会给每一个page cache
他会去创建一个bio
然后
每一个bh它会有一个
bio_vec
这样的一个数据结构那相当于说每一个page cache
每一个页缓存它都有一个bio 对吧
那么接下来一个动作
就是要把这些bio这些脏的page cache
要通过bio这个方式
提交到block layer这儿
那这里我画的这个是
VFS和文件系统这一层
VFS和文件系统层只会管到
这说我的page cache我的bio
接下来我要把bio通过
submit_io这个接口
提交到这个
block layer层这一层
那么这里画的是block layer层
那block layer层它有request_queue
那request_queue里面会把
一个个的
bio链成一个链表
那么接下来就是这个实际上的这个
硬件驱动层就是我们这里的eMMC的驱动
那它会从这个
block layer层去获取这个
刚才提交的这个request
那这里会调用
eMMC的驱动
去处理这个mmc的request
那么这里就是
mmc driver它里面
去处理这个scatterlist
这是buffer
那么我们可以看到
这里面struct scatterlist这个
page_link它指向了我们的page cache
那么最后它会调用到
这个eMMC的这些DMA的
引擎来把这些数据啊
真正的写入到eMMC的这个
这些sector里面就是真正
通过DMA传输来把这些数据
page cache的数据
真正的写入到eMMC里面
那么这个就是
用户空间调用一个write的函数
它怎么把这个
data写入到eMMC的这么一个过程
这里面会涉及到几大块一个是
虚拟文件系统这个write函数这个实现
那这个它实际上只是写到page cache里面
那第二步是说
page cache怎么和这个
buffer_head和bio联系起来
还有这个flush
内核线程它是怎么提交
这个bio的
那么接下来一个是
block layer层它怎么去处理这些
提交的请求那么最后就是实际的这个
块设备驱动它怎么去从block layer层里面去获取
获取这个request然后最后怎么
通过这个eMMC的这个硬件
操作DMA来把数据
真正写到eMMC里面
-1.1 Linux操作系统概述
-1.2 Linux内核结构以及内核模块编程
--Video
-1.3 Linux内核源码中的双链表结构
--Video
-1.4 源码分析-内核中的哈希表
--Video
-1.5 动手实践-Linux内核模块的插入和删除
--Video
-第1章 概述--章节测验
-2.1 内存管理之内存寻址
--Video
-2.2 段机制
--Video
-2.3分页机制
--Video
-2.4 动手实践-把虚拟地址转换成物理地址
--Video
-第2章 内存寻址--章节测验
-3.1 进程概述
--Video
-3.2 Linux进程创建
--Video
-3.3 Linux进程调度
--Video
-3.4 动手实践-打印进程描述符task_struct中的字段
--Video
-3.5工程实践-基于内核模块的负载监控
--Video
-第3章 进程管理--章节测验
-4.1 Linux内存管理机制
--Video
-4.2 进程用户空间管理机制
--Video
-4.3 物理内存分配与回收机制(上)
--Video
-4.4 物理内存分配与回收机制(下)
--Video
-4.5 动手实践-Linux内存映射基础(上)
--Video
-4.6 动手实践-Linux内存映射实现(中)
--Video
-4.7 动手实践-Linux内存映射测试(下)
--Video
-4.8 初学者对内存管理的常见疑惑
-第4章 内存管理--章节测验
-5.1 中断机制概述
--Video
-5.2 中断处理机制
--Video
-5.3 中断下半部处理机制
--Video
-5.4 时钟中断机制
--Video
-5.5 动手实践-中断上半部的代码分析及应用
--Video
-5.6 动手实践-中断下半部的代码分析及应用
--Video
-第5章 中断--章节测验
-6.1 Linux中的各种API
--Video
-6.2 系统调用机制
--Video
-6.3 动手实践-添加系统调用(系统调用日志收集系统)
--Video
-第6章 系统调用--章节测验
-7.1 内核同步概述
--Video
-7.2 内核同步机制
--Video
-7.3 动手实践-内核多任务并发实例(上)
--Video
-7.4 动手实践-内核多任务并发实例(下)
--Video
-第7章 内核同步--章节测验
-8.1 虚拟文件系统的引入
--Video
-8.2 虚拟文件系统的主要数据结构
--Video
-8.3 文件系统中的各种缓存
--Video
-8.4 页高速缓存机制以及读写
--Video
-8.5 动手实践-编写一个文件系统(上)
--Video
-8.6 动手实践-编写一个文件系统(中)
--Video
-8.7 动手实践-编写一个文件系统(下)
--Video
-第8章 文件系统--章节测验
-9.1 设备驱动概述
--Video
-9.2 I/O空间管理
--Video
-9.3 设备驱动模型
--Video
-9.4 字符设备驱动程序简介
--Video
-9.5 块设备驱动程序简介
--Video
-9.6 动手实践-编写字符设备驱动程序
--Video
-9.7工程实践-编写块设备驱动的基础(上)
--Video
-9.8 工程实践-块设备驱动程序分析(中)
--Video
-9.9 工程实践-块设备驱动程序实现(下)
--Video
-第9章 设备驱动--章节测验
-致谢与说明
--Video