Linux设备模型(1)_基本概念

作者:wowo 发布于:2014-2-27 17:01 分类:统一设备模型

1. 前言

在“Linux内核的整体架构”中,蜗蜗有提到,由于Linux支持世界上几乎所有的、不同功能的硬件设备(这是Linux的优点),导致Linux内核中有一半的代码是设备驱动,而且随着硬件的快速升级换代,设备驱动的代码量也在快速增长。个人意见,这种现象打破了“简洁就是美”的理念,是丑陋的。它导致Linux内核看上去非常臃肿、杂乱、不易维护。但蜗蜗也知道,这不是Linux的错,Linux是一个宏内核,它必须面对设备的多样性,并实现对应的驱动。

为了降低设备多样性带来的Linux驱动开发的复杂度,以及设备热拔插处理、电源管理等,Linux内核提出了设备模型(也称作Driver Model)的概念。设备模型将硬件设备归纳、分类,然后抽象出一套标准的数据结构和接口。驱动的开发,就简化为对内核所规定的数据结构的填充和实现。

本文将会从设备模型的基本概念开始,通过分析内核相应的代码,一步一步解析Linux设备模型的实现及使用方法。

2. Linux设备模型的基本概念

2.1 Bus, Class, Device和Device Driver的概念

下图是嵌入式系统常见的硬件拓扑的一个示例:
device_toplogy

硬件拓扑描述Linux设备模型中四个重要概念中三个:Bus,Class和Device(第四个为Device Driver,后面会说)。

Bus(总线):Linux认为(可以参考include/linux/device.h中struct bus_type的注释),总线是CPU和一个或多个设备之间信息交互的通道。而为了方便设备模型的抽象,所有的设备都应连接到总线上(无论是CPU内部总线、虚拟的总线还是“platform Bus”)。

Class(分类):在Linux设备模型中,Class的概念非常类似面向对象程序设计中的Class(类),它主要是集合具有相似功能或属性的设备,这样就可以抽象出一套可以在多个设备之间共用的数据结构和接口函数。因而从属于相同Class的设备的驱动程序,就不再需要重复定义这些公共资源,直接从Class中继承即可。

Device(设备):抽象系统中所有的硬件设备,描述它的名字、属性、从属的Bus、从属的Class等信息。

Device Driver(驱动):Linux设备模型用Driver抽象硬件设备的驱动程序,它包含设备初始化、电源管理相关的接口实现。而Linux内核中的驱动开发,基本都围绕该抽象进行(实现所规定的接口函数)。

注:什么是Platform Bus?
在计算机中有这样一类设备,它们通过各自的设备控制器,直接和CPU连接,CPU可以通过常规的寻址操作访问它们(或者说访问它们的控制器)。这种连接方式,并不属于传统意义上的总线连接。但设备模型应该具备普适性,因此Linux就虚构了一条Platform Bus,供这些设备挂靠。

2.2 设备模型的核心思想

Linux设备模型的核心思想是(通过xxx手段,实现xxx目的):

1. 用Device(struct device)和Device Driver(struct device_driver)两个数据结构,分别从“有什么用”和“怎么用”两个角度描述硬件设备。这样就统一了编写设备驱动的格式,使驱动开发从论述题变为填空体,从而简化了设备驱动的开发。

2. 同样使用Device和Device Driver两个数据结构,实现硬件设备的即插即用(热拔插)。
在Linux内核中,只要任何Device和Device Driver具有相同的名字,内核就会执行Device Driver结构中的初始化函数(probe),该函数会初始化设备,使其为可用状态。
而对大多数热拔插设备而言,它们的Device Driver一直存在内核中。当设备没有插入时,其Device结构不存在,因而其Driver也就不执行初始化操作。当设备插入时,内核会创建一个Device结构(名称和Driver相同),此时就会触发Driver的执行。这就是即插即用的概念。

3. 通过"Bus-->Device”类型的树状结构(见2.1章节的图例)解决设备之间的依赖,而这种依赖在开关机、电源管理等过程中尤为重要。
试想,一个设备挂载在一条总线上,要启动这个设备,必须先启动它所挂载的总线。很显然,如果系统中设备非常多、依赖关系非常复杂的时候,无论是内核还是驱动的开发人员,都无力维护这种关系。
而设备模型中的这种树状结构,可以自动处理这种依赖关系。启动某一个设备前,内核会检查该设备是否依赖其它设备或者总线,如果依赖,则检查所依赖的对象是否已经启动,如果没有,则会先启动它们,直到启动该设备的条件具备为止。而驱动开发人员需要做的,就是在编写设备驱动时,告知内核该设备的依赖关系即可。

4. 使用Class结构,在设备模型中引入面向对象的概念,这样可以最大限度地抽象共性,减少驱动开发过程中的重复劳动,降低工作量。

原创文章,转发请注明出处。蜗窝科技,www.wowotech.net

标签: Kernel 内核 设备模型 Device Model 驱动开发

评论:

东风笑
2018-09-03 15:29
@wowo
博主你好,请教一下为啥2.1的图,有两个线连接到camera上?
小亮
2018-09-03 16:33
@东风笑:博主表示的是I2C控制接口的Camera吧?如果是基于mipi-csi是不是就只有一条呢?
pcszx
2018-09-03 19:56
@小亮:看camera模组吧,mipi-csi通路用来传输数据,CCI(也就是i2c)来控制。
大道无门
2018-08-21 11:07
想知道小哥在哪就职?是哪位大神对linux内核讲的很透彻。
然后, 请小哥多写写关于外围设备驱动的博文,这样会更牛
x。但是这难度极大,光usb就足够吃力了吧,hah
kernel_journey
2018-08-09 10:06
深表同意
windays
2017-08-06 22:43
好文章啊,清晰易懂。
虽然应用起来还需要代码支持,但是对于框架整体的把握帮助很大。
MOLLY
2016-09-01 16:37
我是初学者,你写的我都看懂了,文章浅显易懂,文字精准,属于搞IT里文章写的最好的
wowo
2016-09-02 08:45
@MOLLY:多谢夸奖:-)
paoshapaoxue
2016-07-30 15:22
@wowo:文章写的好,可否在系列的文章里面,加一个下一节的链接,比如在文章linux设备模型1后的末尾加一个linux设备模型2的链接呢?
wowo
2016-07-30 21:18
@paoshapaoxue:多谢建议:-)
不过呢,通常是先写1,后写2。所以就懒懒在写完2之后,再去修改1,将2的链接加进去了。
不过你可以通过右侧的“文章分类”阅读一个系列的文章。
雕兄
2016-04-06 11:14
楼主, 有没有想过把这些子系统模块录制为视频的形式?
wowo
2016-04-06 13:27
@雕兄:我一直有疑问:视频比文字更能帮助理解吗?大家可以讨论一下。
雕兄
2016-04-06 14:03
@wowo:1, 可以知道你分析内核的思路
2, 可以顺便看着代码说
3, 初学者可以快速进入linux内核
freeman
2016-08-24 16:34
@wowo:我觉得视频不能让人高效地学习。视频是一种流媒体,就好像字符设备,基于时序的。这样人们想随机访问视频片段就得来回跳。跳得准跳不准是一回事,就我个人来讲,这样来回跳心也就散了,甚至会机械性地快进,无法保持耐心和专注。文字相比就好很多,可以方便地定位、仔细品味。

另外就我个人来讲,看视频时往往会把自己放在被动地位——视频容量极大可以把知识嚼碎了喂给观众,这样观众容易处于温水煮青蛙的状态。而文字就不一样,不主动去跟随作者的思路、不主动去思考,那结果就是神马也不知道。

最后一点,大部分知识都没有被录成视频。从文字中挖掘知识还是我们大部分时间需要做的事。
wowo
2016-08-25 10:05
@freeman:你的观点和我一样:-)
hony
2017-01-09 22:19
@freeman:赞,有道。
crystal
2016-01-29 10:21
"在Linux内核中,只要任何Device和Device Driver具有相同的名字,内核就会执行Device Driver结构中的初始化函数(probe),该函数会初始化设备,使其为可用状态。"这一句陈述是否略欠考虑,对于usb设备来说,不是有相同名字就行的,而是要usb_bus_type的match函数返回1才行吧?
wowo
2016-01-29 11:11
@crystal:是的,这句话欠妥,但不是“欠考虑”,因为device的probe机制是相当复杂的,可以匹配的case是多种多样的,因而不是几句话就可以罗列完的。所以我就一笔带过了。
很多时候我写文章的方法有些极端,关注简单易懂多于严谨。这样做的出发点是:
对于刚接触这方面知识的工程师来说,概念比细节重要。如果描述的过多过细,反而会带来压力;
而对于已经熟悉这方法知识的工程师来说,他们可以深入到细节里面,轻易发现表述的逻辑问题,然后提出来,大家讨论一下,也皆大欢喜。

回到这句话,其实去kenrel里面看一下代码(每个bus的match回调),就会知道probe的所有依据。蜗窝的目的是引导大家去看,而不应是告诉每一个细节。

不过还是非常感谢您能够指正,您的提问,对读者的帮助才是最大的,因为可以引发思考。
多谢!!欢迎常来~~
crystal
2016-01-29 17:46
@wowo:明白楼主的良苦用心,只是觉得在表述上更加精益求精才好,这对于您以后出书都是很有帮助的,不过还是非常敬佩楼主的分享精神。赞赞赞
wowo
2016-01-29 19:32
@crystal:是的,从其它角度看,确实应该精益求精,虚心接受您的建议,多谢:-)
hony
2017-01-09 22:22
@crystal:可以引发大家的思考——出书会失去一些语言精髓。
wowo
2017-01-10 09:13
@hony:其实书籍有一个毛病:缺乏互动。这一点没有博客方便。
但电子化也有毛病,没有翻一页页纸的感觉爽,哎……
huad_
2016-01-15 11:35
首先,感谢楼主的好文,通俗易懂。
请问,“3. 通过"Bus-->Device”类型的树状结构(见2.1章节的图例)解决设备之间的依赖” 这个图在哪里呢?我没找着
wowo
2016-01-15 12:18
@huad_:文章里面只有那一个图啊,看来那个图画的不好啊,才让老兄你视而不见,呵呵~~~
huad_
2016-01-15 14:08
@wowo:@wowo: 不好意思,看到你这是一系列文章,我以为是链接了别的文章的图,找别的文章去了,让你见笑了~
图画的很好,结构清晰,一目了然。谢谢~
wowo
2016-01-15 14:18
@huad_:不客气~话说文章的图片应该加一个编号的,只怪太懒了。
linux_emb
2015-12-14 10:03
用Device(struct device)和Device Driver(struct device_driver)两个数据结构,分别从“有什么用”和“怎么用”两个角度描述硬件设备。这样就统一了编写设备驱动的格式,使驱动开发从论述题变为填空体,从而简化了设备驱动的开发。
这是我最喜欢的说明方式,把复杂的问题归结到最基本的有什么用和怎么用,简单有效。把论述题变为填空题生动形象。不仅有知识的理解,更有强大的表达能力,小弟佩服。。。。。

发表评论:

Copyright @ 2013-2015 蜗窝科技 All rights reserved. Powered by emlog