百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

LINUX MMC 子系统分析(五)MMC driver模块分析

ahcoder 2025-06-09 19:44 1 浏览

前面我们介绍了MMC 子系统驱动模型、mmc host模块,本篇主要介绍MMC Driver模块,在前面几篇文章中,我们已经说明mmc 子系统已实现mmc driver,即针对所有的mmc card(除 sdio设备外,包括mmc/sd/tf等存储卡),均可以使用该mmc driver。

下面我们分析下mmc 子系统为何实现了统一的mmc driver,主要有如下几点:

  1. Mmc host已提供了访问mmc card的方法(mmc_host->request);
  2. mmc/emmc/sd等协议规范均已定义mmc card(包括mmc/sd/tf等存储卡)支持的命令格式以及状态流转机制、寄存器定义等信息,因此可使用统一的驱动程序实现对所有厂家的card通信(这是由协议规范规定的,比如针对nandflash驱动模块,也不需要为nandflash设备实现特定驱动,因其协议规范也规定了nandflash需要支持的操作及通信格式等等)

基于以上几点,并不需要针对各厂家的mmc card,实现特殊的mmc driver,因此mmc 子系

统实现了统一的mmc driver;

本次介绍的内容包括如下几点:

一、相关的数据结构及关联说明

二、mmc driver的probe/remove

相关的数据结构及关联说明


针对mmc driver而言,相关的数据结构包括mmc_driver、device_driver、device、

mmc_card、mmc_part、mmc_blk_data、mmc_queue、gendisk、request_queue等;

其中mmc_driver为一个mmc card驱动的抽象;device_driver、device为linux设备驱动模型相关的数据结构(该模块已在前面的文章中介绍,此处不再赘述);gendisk、request_queu、request_fn为块设备模型相关的数据结构(此处不展开);mmc_blk_data、mmc_queue主要用于实现mmc block device的通用块层与mmc host之间进行数据传输;而mmc_card则为mmc_driver所要驱动的外设。

这些数据结构之间的关联如下图所示,它们的关联关系说明如下:

  1. Mmc_driver与mmc_card,通过借助设备-总线-驱动模型的数据结构(device_driver、device)及接口,实现绑定与解绑操作;
  2. 针对mmc card,通过mmc_part可定义该mmc card的分区个数及分区大小等内容(mmc card中extended CSD寄存器中存储分区信息,当通过mmc rescan查找到mmc card时,会通过读取该寄存器的值,获取mmc card的分区信息);
  3. mmc_blk_data用于抽象mmc block device信息,这其中包括mmc_queue、request_queue、gendisk这些数据结构;

在完成mmc_driver与mmc_card的绑定过程中,在调用mmc_driver->probe进行设备探测时,则进行mmc block device的创建,针对每一个分区,均执行如下操作:

  1. 创建mmc_blk_data类型的变量,即为每一个分区均创建对应的通用块设备(gendisk类型);
  2. 创建mmc_queue,并为其创建对应的线程及处理接口(主要用于处理来自块I/O子系统的请求);
  3. 针对对mmc_queue,为其创建request_queue及其请求方法mmc_request_fn,并与gendisk进行关联;
  4. 将gendisk注册至块I/O子系统中,从而将本分区对应的通用块设备注册至块设备对应的bdev_map中,类似于字符设备的cdev_map;


本数据结构体包括了mmc driver 子系统、设备-总线-驱动模型、块设备驱动模型、mmc host子系统这几个模块。针对mmc driver的probe而言,也就是完成如下图的数据结构间的关联(remove接口即解除这些数据结构间的关联)。

mmc_driver 数据结构

该数据结构主要包含了device_driver类型的成员,并定义了probe、remove、suspend、resume四个函数指针;这四个函数指针的功能与device_driver中对应的函数指针时对应的。

struct mmc_card数据结构

该数据结构已在上一篇文章中说明,此处不再赘述;

struct mmc_part数据结构

该数据结构用于描述一个mmc card 分区,主要包括分区大小、分区的类型、分区名称、是否为只读分区等信息。mmc card中extended CSD寄存器中存储分区信息,当通过mmc rescan查找到mmc card时,会通过读取该寄存器的值,获取mmc card的分区信息

struct mmc_blk_data数据结构

该数据结构用于抽象一个mmc card 分区对应的block device的数据信息,其中包括:

  1. 该分区对应的通用磁盘设备gendisk,用于将该分区注册至块设备层,以便应用程序可通过块设备I/O访问该分区;
  2. mmc_queue用于抽象mmc 块设备的请求队列,该数据结构中包括了块设备请求队列成员(request_queue及其访问方法,用于处理块I/O层的数据请求信息,并实现将请求分发给mmc host,进而完成与mmc card的数据通信);
  3. 链表成员part用于将该mmc card所有分区对应的mmc_blk_data变量链接至一起;
  4. force_ro、power_ro_lock主要用于描述该分区对应块设备的设备属性信息。


struct mmc_queue数据结构

该数据结构用于描述块设备I/O的request请求,该数据结构包含的内容如下:

  1. card用于指向该队列对应的mmc_card;
  2. thread用于描述该mmc_queue对应的线程,该线程主要用于处理所有从块I/O层下发的请求(request_queue);
  3. request_queue类型的变量用于向块I/O层注册request_queue及其请求方法,以便块I/O层可以将上层的数据请求下发至mmc block层;
  4. issue_fn用于mmc block层将数据请求下发给mmc host层,由mmc host层继续实现数据请求的处理。


Mmc block层的块I/O请求处理

Mmc block层主要借助mmc_queue类型的变量实现块i/o请求,mmc block层提供了块i/o请求处理的线程。块i/o层接口层通过调用mmc block层的request方法(即request_queue->request_fn,即mmc_request_fn接口),该方法通过调用wake_up_process接口,唤醒mmc block层的块i/o处理线程,该线程处理接口则调用mq->issue_fn进行i/o请求的分发,即调用mmc_blk_issue_rq接口,该接口通过一系统的接口调用,最终即调用mmc_host->ops->request,通过mmc_host提供的方法,实现与mmc_card的通信操作。Mmc block层的块i/o处理流程如下所示。

mmc driver的probe/remove

上面介绍了mmc driver层相关的数据结构,通过这些数据结构间的关联图,基本上对mmc driver 的probe/remove接口也

有了一定的了解,而mmc driver的probe/remove接口,也就是完成上述数据结构间的关联的建立与消除。

mmc_driver的定义如注册

mmc_driver的定义如下,该driver的名称为“mmcblk”,主要实现了probe/remove接口以及suspend/resume接口(这两个接口主要用于电源管理)。

mmc_driver与mmc_card的绑定流程

mmc_driver与mmc_card借助设备-总线-驱动模型提供的接口完成,mmc_driver与mmc_card绑定,并执行mmc_driver->probe接口。mmc_driver、mmc_card、mmc_bus之间的绑定流程如下所示:

  1. 通过driver_register与device_register,从而完成mmc_driver、mmc_card、mmc_bus之间的绑定。

(当mmc rescan一个mmc card后,则会创建mmc card,并同时调用device_register,将该mmc_card注册至mmc_bus中,并触发__device_attach,从而完成mmc_card与mmc_driver的绑定,并调用mmc_driver->probe,即调用mmc_blk_probe接口,实现mmc block device的创建及注册流程。)

mmc_blk_probe

mmc_blk_probe实现的功能如下:

针对该mmc card的每一个分区,均执行如下操作:

  1. 为每一个分区,创建对应的通用磁盘设备gendisk;
  2. 设置gendisk的fops为mmc_bdops;
  3. 为每一个通用磁盘设备,均创建request_queue及其处理方法;
  4. 为该通用磁盘设备创建mmc block块i/o请求机制;
  5. 将该分区对应的通用磁盘设备注册至块设备i/o中,以便应用层可通过块设备访问该mmc card 分区。


mmc_driver与mmc_card的解绑流程

当mmc card rescan机制,检测到mmc card移除后,在mmc card release的过程中,即调用device_unregiser接口,完成解绑流程,从而触发mmc_blk_remove接口的调用,完成解绑操作。而mmc_blk_remove接口的主要功能如下:

针对每一个mmc card分区,均执行如下操作:

  1. 将该分区对应的mmc 块请求处理机制删除;
  2. 将该分区对应的通用磁盘设备从块设备模块中移除;
  3. 解除mmc_card与mmc_host的关联;


以上即为本篇文章的主要内容,本篇文章主要说明mmc_driver与mmc_card的绑定与解绑流程,并说明了mmc block device的创建与删除流程等内容,本章的内容不需要驱动开发人员进行更改,这些内容均为mmc子系统实现,此处主要用于帮助我们理解mmc子系统。

相关推荐

MySQL的数据类型和存储引擎介绍(mysql数据存储种类)

一.MySQL数据类型1.整数类型注:MySQL可以为整数类型指定宽度,比如int(3)、int(5),这个限制不是限制value的合法范围,所以对绝大数应用没有任何意义,对于存储而言,int(...

Linux目录管理(linux目录权限详解)

创建、复制、删除、移动、查看、编辑、压缩、查找内容提要:目录结构如图1-1所示bin普通用户使用的命令/bin/ls,/bin/datesbin管理员使用的命令/sbin/server如图1-2所...

C语言中的变量,在内存中如何存储?

在C语言中,提供了char,int这样的变量类型,可以定义一个变量,然后,在变量中存储数据。例如:charx=68;就是定义了一个char类型的变量,变量的名称是x,在x这个变量中存放68...

Redis进阶之底层存储数据结构及内存优化

前言Redis作为高性能缓存中间件,除了拥有高性能的特点之后,相比于其他缓存而言还支持多种数据结构,而如String、List、Set、SortedSet和Hash都是redis对外支持的数据结构,而...

在Centos8 中使用Stratis管理本地存储(一)

Stratis是RHEL8/Centos8中提供的一个新的本地存储管理工具,它将有助于在块设备上创建分层存储。在RHEL8/Centos8中,可以通过安装两个软件包获得Stratis。在RHEL7,我...

Linux基金会2015 Vault大会:专攻存储、文件系统

IT之家(www.ithome.com):Linux基金会2015Vault大会:专攻存储、文件系统谈到云计算,我们常常想到微软、Azure等词语。其实也不然,Linux在云计算适用性更强,例如运行...

安卓16大升级!Linux终端存储突破42.3GB,手机变电脑真香了?

IT之家4月20日消息,谷歌Pixel手机用户迎来重磅升级!安卓16Beta4版本中,Linux终端应用彻底解除存储限制,用户可自由调用手机全部存储空间,实测扩容至42.3GB,让手机秒变生产力工...

Linux下ISCSI存储部署教程(iscsi存储优缺点)

在Linux系统下部署iSCSI存储是一项常见的任务,它能够为系统提供远程块级存储,使多个服务器可以通过网络访问共享的存储设备。iSCSI是一种基于TCP/IP的协议,通过IP网络来传输SCSI指令,...

如何在 Linux 系统中永久禁用交换分区 ?

Linux操作系统中的交换分区或交换文件充当硬盘上的临时存储区域,当物理内存(RAM)满时,系统使用该存储区域。它用于交换较少使用的内存页,这样系统就不会因为运行应用程序而耗尽物理内存。随着技术的发...

如何使用 Chmod 更改 Linux 上的文件和文件夹权限?

在Linux的世界里,权限就是秩序的基础。一个系统的安全性、文件访问策略、用户协作边界,无一不依赖于文件和目录权限的精细控制。而chmod(ChangeMode)命令,正是你手中调整权限的利剑...

掌控进程优先级:深入理解 Linux 的 Nice 与 Renice 命令

在日常的Linux系统管理中,资源调度是一个绕不开的话题。当系统负载过高、响应变慢,我们往往会寻找高资源占用的“罪魁祸首”,但我们还能做得更多——「调整这些进程的“优先级”」,让关键任务跑得更快,...

Linux修改uboot启动延时方法详细攻略,触觉智能RK3568开发板演示

本文介绍Linux系统修改uboot启动延时方法,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持开源鸿蒙OpenHarmon...

Linux基本命令—修改命令别名(linux怎么修改命令)

输入命令后系统的执行过程:alias(别名)—>内部命令—>hash表(记录外部命令的路径)—>$PATH(变量)—>命令找不到命令别名修改临时:aliascdnet=...

文件系统和模块设备的Page cache问题

一,普通文件的addressspace文件系统读取文件一般会使用do_generic_file_read(),mapping指向普通文件的addressspace。如果一个文件的某一块不在page...

LINUX MMC子系统分析(四) MMC HOST模块分析

本章主要介绍mmchost相关的内容,包括mmc子系统提供的mmchost相关的接口,以及mmchost与mmccard等子模块的关联等内容。我们按如下几部分进行介绍:一、相关的数据结构体及关...