DM 3730的I2C控制器框架如图7-4所示。图7-4引自《DM 3730芯片手册》中第2798页的框图。关于DM 3730I2C的驱动部分,主要分析相关初始化和总线传输的操作。由于I2C作为控制和获取状态信息,数据量并不大,而且相关的操作频率并不高,这样在中断中进行相关的处理,对系统的影响并不大。......
2023-11-22
1ᤫ整体框架
要了解块设备首先要从系统层面了解块设备所在的位置和上下层的关系,如图5-20所示。
图5-20 块设备在系统中层次关系
从图5-20可见,块设备层既可以作为裸设备来供应用层使用,也可以作为物理文件系统的承载设备与文件系统进行关联。为了提升整个系统的性能,在块设备层之上增加了buffer层来缓冲数据,buffer是缓存在内存中,所以物理上会将多个buffer组织在page中,整体形成pagecache。这种架构满足了之前涉及的需求,并兼顾灵活性与整体的性能。
块设备层的内部设计同样要考虑性能,从整体上块设备的内部框架如图5-21所示。从图5-21可见,块设备的框架层次还是很灵活的,可以为了满足某种需求,设计虚拟块设备实现如负载均衡等高级的功能;为了整体性能和吞吐量,增加了IO scheduler层来优化物理设备的读写性能;也可以跳过IO scheduler层直接进行块设备操作。总体上讲,这种内部框架可以把分层的驱动综合起来实现复杂的功能。
图5-21 块设备内部框架
2ᤫ核心管理实体
从整体的层次上看,块设备需要有针对文件系统和VFS的接口实体,另外还需要管理生命周期的设备模型相关实体以及驱动管理实体。除此之外块设备的数据是以块为单位,自然在操作上要有相关的单位操作管理实体以及管理方法,这些就形成了驱动。
针对以上的分析,来看看Linux内核的具体实现,块设备主要管理实体及系统关系如图5-22所示。
图5-22中主要涉及的管理实体是block_device、hd_struct和gendisk。与操作相关的是re-quest和bio结构,另外图中还涉及与buffer/page cache的关系。buffer/page cache是将文件系统等非内存空间的数据存放在内存页面中,所以在系统结构上通过内存管理的page以及地址转换管理address_space(可以根据不同的内容重载为不同的管理操作)实现这部分的管理,块设备的数据单元块在内存中通过buffer_head进行管理,一个物理页中会存放多个块,而物理页的管理实体page会通过链表对buffer head进行管理,进而管理其中存放的块。而page中的private和标识共同表示其中管理的是buffer_head链表。buffer_head和page是通过attach_page_buffers来进行关联该函数会通过set_page_private来设置page的private属性,这样通过page,buffer_head以及address_space就实现了buffer/page cache的管理。涉及块设备层和上层之间的缓冲操作也可以通过该框架实现,只要实现不同的address_space操作即可。
物理的块设备(如硬盘)通常可以进行分区,而不同分区在用户看来是不同的设备。硬盘本身同样是设备,这样实际就有设备层次,需要在文件系统层面能够了解这种设备层次,是设备管理的需求,否则用户无法了解某个分区及物理磁盘的关系。这就要求块设备对应的文件系统相关的管理实体能够表现这种层次关系。同一个物理磁盘,相关的操作没有差别,与之上的文件系统没有关系,所以驱动管理实体并不需要每个分区有一个,为了实现数据的批处理操作相应的操作数据需要以链表的形式存在。再者在块设备层与文件系统的接口管理实体中直接表示硬件的分区信息是不合适的,所以也要一个实体进行物理分区的管理,分区本身就是实际的逻辑设备,所以也会将设备模型相关的管理归入其中。以上的管理都是通过管理实体block_device、hd_struct和gendisk来实现的。它们之间各种关系的细节如图5-23所示。
图5-22 块设备层各实体及系统关系框图
从图5-23可见,文件系统中的设备层次由block_device来实现,驱动的管理实体通过gendisk来进行管理,hd_struct进行物理的分区管理,同时为设备模型的接口。这样各种结构的功能就明确了,接下来看看细节。
图5-23 块设备内部管理实体关系框图
先看看block_device的主要信息:
从其中的属性可见与VFS以及具体的文件系统都会有关联,这点不难理解。设备本身可以作为文件提供给用户,另外块设备还是具体的文件系统的承载,这两点都要体现,就都需要关联彼此了。
接下来看看hd_struct的主要信息:
其中不仅包含了物理分区的信息还与设备模型有关联,毕竟分区就是对应着物理的设备。相应的设备模型的管理主要是在设置__dev上,在add_partition中的设置如下:
可见相关操作时初始化device实体并分配设备号,其中device关联特定的part_type类型,生命周期结束时可以释放相关的空间。整个磁盘又是如何与设备模型相关联呢?这就需要看看gendisk:
可见其中嵌入了structhd_struct part0;这样既有了整体disk的物理信息又可以与设备模型相关联。在alloc_disk中会调用alloc_disk_node,其中包含如下代码:
这里设置的设备模型相关类型为disk_type,可以对disk进行生命周期管理,在必要的时候可以释放其中分区的信息。
3ᤫ驱动管理及块设备驱动流程
块设备层的驱动管理工作同样是由kobj_map来实现的,kobj_map中的内容之前在字符设备中已经进行了介绍,下面看看块设备层是如何使用它完成驱动管理的。
驱动管理要涉及设备号的范围及管理实体,块设备层将其封装为blk_register_region,细节如下:(www.chuimin.cn)
下面来看看具体的管理实体是什么?相关在add_disk中的实现如下:
从代码分析可见,驱动管理实体是gendisk,在注册驱动管理实体的同时还向sys文件系统注册一些属性,以便运行时可以进行相关设置。
块设备驱动管理的子设备号由具体的块设备进行设置,因为这和其能力相关,块设备层提供了alloc_disk接口进行相关操作。
驱动管理实体gendisk的细节如图5-24所示。
图5-24 块设备驱动管理实体
从图5-24可见,其中主要包括设备的控制操作接口block_device_operations,以及与设备数据流相关的数据队列及操作。block_device_operations中主要是对设备打开、关闭,以及换盘等控制操作的接口。这样设计的原因是:块设备是文件系统的物理基础,而物理文件系统不会调用VFS中的文件接口(这样做使得层次混乱),所以相关的控制操作通常会在块设备层中进行封装,比如blkdev_get就会进行设备open的操作,这样可以为上层各种需求提供统一的接口。
块设备数据流请求的具体关系以一个例子进行说明,如图5-25所示。
图5-25中的一次操作的请求是读取连续16KB的数据,由于Linux内核中将sect定义为512B,所以是32个sect。相应的请求拆成两个bio进行操作,每个bio为8KB的操作,对应到内存的两个page,相应分配bio_vec的数组为2会关联到两个物理页面的管理实体。实际的操作就是在页面与bio之间进行,通常这些块设备DMA的操作通过散列式DMA的方式实现,以提高整体的性能。
图5-25 块设备数据请求例子
针对块设备的数据操作流程,块设备层统一提供了操作单元bio,相应的起始操作接口是submit_bio,从submit_bio到请求队列的流程如图5-26所示。
图5-26 submit_bio到请求队列流程
从图5-26可见,在真正处理请求之前是可以对请求进行合并等操作的,这样保证最终执行的请求尽可能的集中,以减少如机械硬盘等有机械件的块设备的机械操作。
通常情况下具体块设备相应的请求处理流程如图5-27所示。
图5-27 一般块设备请求处理流程
从图5-27可见,上层下发的请求是完全按照顺序进行处理的,其中请求队列中的re-quest_fn通常是唤醒具体块设备的驱动进程进行实际的请求处理,这样将上层与驱动分开在不同的执行实体执行,可以通过对数据进行批处理操作,从而提高整体的性能。
从系统的角度,IO性能除了吞吐量外,还要考虑不同应用IO请求的响应延时。如果只是按照顺序进行块设备的请求处理并不能很好地满足各种响应延时的需求,所以需要在请求执行过程中加入调度的机制,就是IO scheduler,来提升整体的性能。由于这些都是对实际操作请求的调整,所以都被包含在request_queue中,不同的IO scheduler方式由struct eleva-tor_type来定义,主要的操作接口包含在struct elevator_ops中。request_queue如果使用IO Scheduler则逻辑上有两套queue,一个是IO scheduler使用的queue;另一个是物理驱动操作的queue。具体的流程如图5-28所示。
从图5-28可见,真正对请求的操作顺序是会依据之前的IO操作重新调整顺序的,作为内核块设备层可以实现一个反馈系统,从而尽力满足所有用户的性能需求,提高整体的IO性能。当然不会有对所有情况都满足的调度方法,所以Linux内核提供了很多种IO scheduler方法,如CFQ、Deadline等以适应不同的需求。系统可以通过elevator_switch来进行不同调度算法之间的切换。由于IO scheduler是与算法紧密相关的这里就不进行详细的分析。
图5-28 带io scheduler的块设备请求处理流程
4ᤫ块设备驱动初始化
针对块设备驱动,块设备层提供了很多接口包括如何操作请求队列(start,stop,延时操作等),还提供了默认生成request的接口__make_request,但是只有一个接口request_fn需要由驱动提供,前面提到了该接口是具体唤醒驱动请求处理的函数,也是和具体驱动关系最紧密的部分,相关的初始化就是要将驱动特定的request_fn接口加入request_queue中,Linux内核通过blk_init_queue生成包含驱动特定接口的request_queue来实现该功能。具体驱动的初始化流程如图5-29所示。
从图5-29可见,对于具体的块设备驱动中最重要的两部分就是request_fn和中断。re-quest_fn负责下发请求并唤醒处理罗辑;中断则负责处理之后的流程唤醒。两者完整的结合实现整体数据操作。
图5-29 具体驱动的初始化流程
在块设备框架层,具体的块设备驱动初始化一般按照以下流程实现:首先需要通过al-loc_disk来分配驱动管理实体gendisk;然后将blk_init_queue生成的设备自身request_queue加入到gendisk中;最后通过add_disk来将驱动管理实体加入系统进行管理。这样系统就可以通过驱动进行操作了。
有关深入剖析Linux内核与设备驱动的文章
DM 3730的I2C控制器框架如图7-4所示。图7-4引自《DM 3730芯片手册》中第2798页的框图。关于DM 3730I2C的驱动部分,主要分析相关初始化和总线传输的操作。由于I2C作为控制和获取状态信息,数据量并不大,而且相关的操作频率并不高,这样在中断中进行相关的处理,对系统的影响并不大。......
2023-11-22
图3-3Linux内核整体框架③bridges:桥梁层。Linux内核通过统一的接口操作设备,这样就屏蔽了各个设备的差异,从而降低了和硬件的耦合关系。Linux内核为了简化实现,将共享资源的进程作为线程。考虑到外部事件需要对执行流程进行转换,另外不同的应用执行流程之间需要切换,这就要在Linux内核的逻辑层抽象出调度器这一逻辑功能。......
2023-11-22
考虑到电源管理的需求涉及处理器和各种设备,一方面是处理器尽可能减少功耗,另一方面是设备尽可能减少功耗。图5-30Linux电源管理各个功能从图5-30可见Linux内核的电源管理功能有与处理器相关的CPUIdle和CPUFreq,也有与设备相关的runtime pm,另外还有与整个系统待机时SLM相关的低功耗电源管理功能。下面分别对这些功能框架进行介绍。具体的驱动同样会在SoC电源管理部分进行讲解。对具体设备的电源管理实现,将在设备驱动中进行详细分析。......
2023-11-22
对视频应用来说,主要就是获取视频流的操作。设备的适配同样需要实现HAL层,相应的HAL层实体初始化的操作如下:Android框架加载了相应的HAL模块后,就会通过相应的camera_ops来操作,而这些操作都是适配操作,实际上是调用V4L2CameraHardware中的实际为CameraHardware的函数。Android的适配在使用流程上与应用的实例是相同的,只是在操作上封装成不同的接口,而且将参数与数据流控制分离,这样方便了管理,也易于与其他模块交互。......
2023-11-22
也正是因为Linux内核的唯一性,各个不同发布版本拥有相同的框架。Linux内核是在整个Linux系统的最底层,它负责管理硬件,运行用户程序,并保持系统整体的安全性和完整性。可以说是Linux系统的根和灵魂。图3-1中看到Linux内核还有另一层面的含义。这对于Linux内核同样适用。所以对Linux内核的剖析、学习和研究也不能独立于系统进行,而是要综合考虑应用、内核和硬件等各方面的信息和内容。这样才能更全面、深刻地理解Linux内核。......
2023-11-22
整个系统启动和初始化的过程,Linux内核是在主处理器启动之后才会执行。不同的处理器启动流程并不相同,这就要求Linux内核能支持各种处理器的初始化操作。Linux内核各个模块,大部分设计时做到了体系结构无关。Linux内核是一个庞大的系统,最终生成的操作系统代码的执行文件非常大。......
2023-11-22
VFS的实现是以“一切皆是文件”为需求出发点的。要理解VFS的框架首先看一下VFS和系统的静态关系框图,如图5-1所示。从图5-1可见,VFS是用户层的直接接口,是面向用户的服务。图5-1VFS和系统静态关系图在图5-2中每个节点被使用时都会在VFS层中创建dentry,这样可以快速通过文件名进行查找和定位,Linux内核中对dentry的管理组织形式如图5-3所示。以上是系统运行时VFS对文件名的组织管理,这是VFS管理的一个方面。......
2023-11-22
USB的设计为非对称式的,它是主从式总线,任何USB事务都是由主机引发的。USB总线拓扑如图7-12所示。图7-12引自《USB2.0规范》。USB总线已经成为使用最广泛的设备连接标准。每个USB设备至少有两个端点/管道,分别是进和出两个方向,编号为0,用于控制总线上的设备。总体上来说,系统对USB总线驱动的需求就是要能按规范实现总线的各种功能,并且满足总线的各种无关性的需求。......
2023-11-22
相关推荐