热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

转linux设备模型(4)

作者:wwang出处:http:www.cnblogs.comwwang本文采用知识共享署名-非商业性使用-相同方式共享2.5中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须

作者:wwang 
出处:http://www.cnblogs.com/wwang 
本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

《Linux设备模型 (2)》和《Linux设备模型 (3)》主要通过一些简单的实作介绍了kobject、kset、kobj_type、attribute等数据结构的用法,但这些实作并没有涉及到实际环境下的设备模型和sysfs。本文将以/sys下的module子目录为例,看看内核是如何构建sysfs这棵大树的。

(注:本文的分析基于2.6.36内核)

module的创建

当module被insmod到内核空间时,/sys/module目录下会相应创建一个和模块同名的目录。我们以usb_storage为例,在执行完sudo modprobe usb_storage之后,sysfs里会产生一个名为usb_storage的目录,其目录结构是:

,

在Linux 2.6内核里,module的插入是由用户程序insmod(modprobe最终也是调用insmod)发起的,但大部分工作还是由内核完成。我们可以用strace来观察一下insmod的流程。

stat64("/sys/module/usb_storage", 0xbfb9a654) = -1 ENOENT (No such file or directory)
open("/lib/modules/2.6.35-24-generic/kernel/drivers/usb/storage/usb-storage.ko", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=94776, ...}) = 0
mmap2(NULL, 94776, PROT_READ|PROT_WRITE, MAP_PRIVATE, 3, 0) = 0xb776f000
close(3)                                = 0
init_module(0xb776f000, 94776, "")      = 0
munmap(0xb776f000, 94776)               = 0
exit_group(0)                           = ?

从这个流程我们可以看到,insmod在执行时,首先会把module的内容映射到内存里,然后呼叫系统调用init_module来实现真正的工作。

,

如上图所示,这是系统调用init_module的执行路径。因为本文只是讨论设备模型和sysfs,流程图里只涉及到相关的内容。 

1、mod_sysfs_init首先会查询当前模块(本例中是usb_storage)在sysfs中是否已经存在,如果没有,则调用kobject_init_and_add创建之;

2、调用kobject_create_and_add创建holders目录。holders目录用于存放指向其他module的链接,这里的其他module都是依赖于当前module的。以usb_storage为例,如果我们需要使用ums_XX模块(比如ums_karma或者ums_freecom等),可以调用sudo modprobe ums_XX来完成加载,因为ums_XX依赖于usb_storage,所以在usb_storage/holders目录下就会创建指向ums_XX的链接,同时refcnt也会加1;

3、module_param_sysfs_setup用来创建parameters目录,这个目录里的文件对应着当前module的所有参数。在Linux内核里,module的二进制ko文件中的__param section用来存储当前module的参数,load_module会把这些参数读取到内存结构里,module_param_sysfs_setup再根据相应的结构来创建paramters目录及其参数文件;

4、module_add_modinfo_attrs用来创建当前module目录下的4个文件:version、srcversion、refcnt和initstate,其中version和srcversion的信息存储在二进制ko文件的.modinfo section里。对于usb_storage模块来说,并没有指定version,所以不存在version这个文件。顺便罗嗦一句,在Linux内核里,可以用宏MODULE_VERSION定义版本号,比如MODULE_VERSION("v1.00")定义版本号为v1.00,这里的版本信息完全是字符串,并无特定格式。srcversion可以由MODULE_INFO(srcversion, xxx)来定义,但一般情况下由modpost默认生成就可以了。refcnt反映当前module的引用计数。initstate反映module的三种状态:live、coming和going;

5、add_usage_links和holders是密切相关的,但这个函数并不是操作当前module的holders目录。以ums_XX为例,在ums_XX的加载过程中,其add_usage_links会把自己作为链接加到usb_storage的holders目录下;

6、sections目录对应当前module的二进制ko文件里的section信息,这是通过add_sect_attrs实现的。需要提醒一下的是,section的命名通常以“.”开头,而以“.”开头的文件在Linux里被认为是隐藏文件,所以如果要察看的话要在ls命令后加"-a"参数,下面谈到的notes同样需要这样处理;

7、add_notes_attrs用来创建notes目录。ELF文件格式定义了一种名为note的元素,主要用于给二进制文件添加一些标示信息。通常,我们可以用readelf来察看ELF文件是否包含note section。比如usb_storage,我们可以使用命令“readelf usb-storage.ko -n”察看,其输出如下:

Notes at offset 0x00000034 with length 0x00000024:

Owner Data size Description

GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)

相应的,在/sys/module/usb_storage/notes目录下建立的notes文件就是.note.gnu.build-id。

上面的7条流程里,并无创建drivers的地方,那/sys/module/usb_storage下的drivers目录是如何建立的呢?答案在下图:

, 

在usb_storage的module_init中,会调用usb_register来注册usb_driver结构,如图中所示,最终会调用module_add_driver来创建drivers目录。

module的撤销

module的撤销过程和前文中的创建过程一一对应,在这里就不详细叙述了,请看下图。

, 

关于sysfs中的其他子目录的创建和撤销,大家也可以很容易的在Linux内核中找到对应的代码,本文不再一一赘述。

转 linux设备模型(4)


推荐阅读
  • 利用ipv6技术,废旧笔记本变成server
    如果你家的路由器已经get到了ipv6地址,并且你家的电脑也获取了有效的ipv6地址,在广域网的设备可以访问到。那恭喜你,再配合我这个dd ... [详细]
  • ARToolKitunity
    ARToolKit为开源的AR库,相对于高通和easyAr有几点特点:1)开源2)识别项目可以动态添加(详细在后)3)识别文件可以本地生成4)目前只能识别图片(目前为.jpg格式) ... [详细]
  • Spark 贝叶斯分类算法
    一、贝叶斯定理数学基础我们都知道条件概率的数学公式形式为即B发生的条件下A发生的概率等于A和B同时发生的概率除以B发生的概率。根据此公式变换,得到贝叶斯公式:即贝叶斯定律是关于随机 ... [详细]
  • 安全3AAuthentication:认证Authorzation:授权Accouting|Audition:审计用户管理用户:UID:0,不一定是root,root的uid非0时 ... [详细]
  • ASP.NET Core WebAPI 开发新建WebAPI项目  转
    转 http:www.cnblogs.comlinezerop5497472.htmlASP.NETCoreWebAPI开发-新建WebAPI项目ASP.NETCoreWebAPI ... [详细]
  • UDP协议开发
    UDP是用户数据报协议(UserDatagramProtocol,UDP)的简称,其主要作用是将网络数据流量压缩成数据报形式,提供面向事务的简单信息传送服务。与TCP协议不同,UD ... [详细]
  • 这篇文章主要简要记录了对于研发团队工作的质量 ... [详细]
  • AsyncDisplayKit2.0教程(下)
    AsyncDisplayKit2.0Tutorial:AutomaticLayout原文:AsyncDisplayKit2.0Tutorial:Automatic ... [详细]
  • webpack 配置IP 和端口号
    最近在用webpack搭建本地服务器的时候,因为不想总是用localhost来跑,所以对webpack.config.js进行了配置,如下devServer:{publicPath ... [详细]
  • Adapter相当于C(Controller,控制器),listView相当于V(View,视图)用于显示数据为ListView提供数据的List,数组或数据库相当于MVC模式中的 ... [详细]
  • C#设计模式(8)——桥接模式(Bridge Pattern)
    原文地址:http:www.cnblogs.comzhilipBridgePattern.html原文作者:Learninghard原文出处:博客园一、引言 ... [详细]
  • Jmeter的聚合报告
       ... [详细]
  • 摘自:https:www.cnblogs.comnick-huangp4076273.htmlselect*from(select'Nick'asitemfromd ... [详细]
  • CentOS7.2详细安装步骤(二)
    7)语言设置(可以在上一个主界面进行设置,这里不用再次设置)8)SECURITY设置(安全设置)选择default(默认的)策略就可以,通过进行选择,单击完成即可Default#默 ... [详细]
  • SortalinkedlistinO(nlogn)timeusingconstantspacecomplexity.这道题属于人生中第一次对链表进行操作,首先,不同于C++中的st ... [详细]
author-avatar
王先生
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有