转:http://www.360doc.com/content/11/1218/16/1299815_173168170.shtml

sysfs把连接在系统上的设备和总线组织成为一个分级的目录及文件,它们可以由用户空间存取,向用户空间导出内核数据结构以及它们的属性,这其中就包括设备的主次设备号。新的设备文件系统udev的工作过程就依赖于sysfs文件系统的这些功能特点。udev文件系统在用户空间工作,它可以根据sysfs文件系统导出的信息(设备号(dev)等),动态建立和删除设备文件(下文详细介绍),而不再需要使用mknod来手动建立设备文件,也不必为查找设备号(尤其是驱动中动态申请产生的设备号)而头疼。

kobject内核对象提供了基本的对象管理能力,是linux 2.6设备模型的核心结构,每个在内核中注册的kobject对象都对应于sysfs文件系统的一个目录,这可以通过以下函数调用体现:

kobject_add()-> kobject_add_varg()->kobject_add_internal()->create_dir()->sysfs_create_dir()

(好像已经不存在kobject_register函数了)

sysfs文件系统下的所有目录,其最终的建立过程都是通过注册添加kobject到linux设备层次来实现的,举两个例子:

1、class

class_register-> __class_register-> kset_register-> kobject_add_internal

2、device

device_register-> device_add-> kobject_add

因此,对应于一个设备,在sysfs文件系统下不是一个文件,而是一个目录,目录名字的来源是kobject对象的name域。目录中会有两个文件和若干目录,这两个文件是设备的属性文件。我们可以看看device_add函数的实现,其中有:

912 error = device_create_file(dev, &uevent_attr);

913 if (error)

914 goto attrError;

915

916 if (MAJOR(dev->devt)) {

917 error = device_create_file(dev, &devt_attr);

918 if (error)

919 goto ueventattrError;

其中会在sysfs文件系统对应设备目录下创建两个属性文件(可以看看device_create_file函数的实现,是调用sysfs_create_file),其中有两个参数是两个结构体指针,两个结构体的定义如下:

311 static struct device_attribute uevent_attr =

312 __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);

428 static struct device_attribute devt_attr =

429 __ATTR(dev, S_IRUGO, show_dev, NULL);

再看看_ATTR:

48 #define __ATTR(_name,_mode,_show,_store) {

49 .attr = {.name = __stringify(_name), .mode = _mode }, \

50 .show = _show, \

51 .store = _store, \

52 }

再看看__stringify:

19 #define __stringify_1(x) #x

20 #define __stringify(x) __stringify_1(x)

(真是无底洞呀,到这为止吧!)这两个宏看起来很怪异,有人说这个定义很奇妙,具体奇妙在哪目前我还没体会到,等有机会再补充(留个脚印吧)。简单来说,它们的功能就是x转化为字符串,所以uevent和dev就转化为“uevent”和”dev“了,把它们赋给name,这就是sysfs具体设备目录下的两个文件uevent和dev名字的来源了!

这两个属性文件的内容是怎么等到的呢?sysfs是虚拟文件系统,大家应该知道proc文件系统吧,类似地它们都是在内存中,内容都是动态生成的而不是存储在非易失存储器中。大家应该注意到属性结构体中有两个函数指针show和store,在这里被赋值了

422 static ssize_t show_dev(struct device *dev, struct device_attribute *attr,

423 char *buf)

424 {

425 return print_dev_t(buf, dev->devt);

426 }

您可能想知道 sysfs 是怎么认出系统中存在的设备以及应该使用什么设备号。对于已经编入内核的驱动程序,
   当被内核检测到的时候,会直接在 sysfs 中注册其对象;对于编译成模块的驱动程序,当模块载入的时候才会这样做。一旦挂载了 sysfs 文
   件系统(挂载到 /sys),内建的驱动程序在 sysfs 注册的数据就可以被用户空间的进程使用,并提供给 udev 以创建设备节点。

udev 初始化脚本负责在 Linux 启动的时候创建设备节点,该脚本首先将 /sbin/udevsend 注册为热插拔事件处理程序。热插拔事
   件(随后将讨论)本不应该在这个阶段发生,注册 udev 只是为了以防万一。然后 udevstart 遍历 /sys 文件系统(其属性文件dev中记录这设备的主设备号,与次设备号),并在 /dev 目录下创建符合描述的设备文件。例
如,/sys/class/tty/vcs/dev 里含有"7:0"字符串,udevstart 就根据这个字符串创建主设备号为 7 、次设备号为 0
的 /dev/vcs 设备。udevstart 创建的每个设备的名字和权限由 /etc/udev/rules.d/
目录下的文件指定的规则来设置。如果 udev 找不
   到所创建设备的权限文件,就将其权限设置为缺省的 660 ,所有者为 root:root 。

上面的步骤完成后,那些已经存在并且已经内建驱动的设备就可以使用了,那么以模块驱动的设备呢?
   前面我们提到了"热插拔事件处理程序"的概念,当内核检测到一个新设备连接时,内核会产生一个热插拔事件,
   并在 /proc/sys/kernel/hotplug 文件里查找处理设备连接的用户空间程序。udev 初始化脚本将 udevsend 注册为该处理程序。
   当产生热插拔事件的时候,内核让 udev 在 /sys 文件系统里检测与新设备的有关信息,并为新设备在 /dev 里创建项目。

大多数 Linux 发行版通过 /etc/modules.conf 配置文件来处理模块加载,对某个设备节点的访问导致相应的内核模块被加载。对 udev 这
   个方法就行不通了,因为在模块加载前,设备节点根本不存在。为了解决这个问题,在 LFS-Bootscripts 软件包里加入了 modules 启动脚
   本,以及 /etc/sysconfig/modules 文件。通过在 modules 文件里添加模块名,就可以在系统启动的时候加载这些模块,这样 udev 就
   可以检测到设备,并创建相应的设备节点了。如果插入的设备有一个驱动程序模块但是尚未加载,Hotplug 软件包就有用了,它就会响应
   上述的内核总线驱动热插拔事件并加载相应的模块,为其创建设备节点,这样设备就可以使用了。

udev是一种工具,它能够根据系统中的硬件设备的状况动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下,
   使用udev 后,在/dev下面只包含系统中真实存在的设备。它于硬件平台无关的,位于用户空间,需要内核sysfs和tmpfs的支持,sysfs为
   udev提供设备入口和uevent通道,tmpfs为udev设备文件提供存放空间。
 
   显而易见udev设备文件的优点:
   1.udev完全在用户态工作,利用设备加入或移除时内核所发送的热插拔事件。在热插拔时,设备的详细信息会由内核输出到位于/sys的sysfs
   文件系统。udev的设备命名策略权限控制都在用户态完成的,它利用sysfs信息来进行创建设备文件节点。
   2.udev根据系统中的硬件设备的状态动态更新设备文件,进行设备文件的创建和删除等。
   注:使用udev,/dev目录下就会只包含系统中真正存在的设备。
  
   注:所有在 sysfs 中显示的设备都可以由 udev 来创建节点。如果内核中增加了其它设备的支持,
   udev 也就自动地可以为它们工作了。在init初始化之前,udev 可以被放入 initramfs 之中,并在每个设备被发现的时候运行。
   也可以让udev 工作在一个真的根分区被加载之后根据 /sys 的内容创建的初始 /dev 目录之中
  
三.>udev和devfs设备文件的对比
1.udev能够实现所有devfs实现的功能。但udev运行在用户模式中,而devfs运行在内核中。
2.当一个并不存在的 /dev 节点被打开的时候, devfs一样自动加载驱动程序而udev确不能。
  udev设计时,是在设备被发现的时候加载模块,而不是当它被访问的时候。
  devfs这个功能对于一个配置正确的计算机是多余的。系统中所有的设备都应该产生
  hotplug 事件、加载恰当的驱动,而 udev 将会注意到这点并且为它创建对应的
  设备节点。如果你不想让所有的设备驱动停留在内存之中,应该使用其它东西来
  管理你的模块 (如脚本, modules.conf, 等等) 。
  其中devfs 用的方法导致了大量无用的 modprobe 尝试,以此程序探测设备是否存在。
  每个试探性探测都新建一个运行 modprobe 的进程,而几乎所有这些都是无用的。
 
3.udev是通过对内核产生的设备名增加别名的方式来达到上述目的的。前面说过,udev是用户模式程序,不会更改内核的行为。
因此,内核依然会我行我素地产生设备名如sda,sdb等。但是,udev可以根据设备的其他信息如总线(bus),生产商(vendor)等
不同来区分不同的设备,并产生设备文件。udev只要为这个设备文件取一个固定的文件名就可以解决这个问题。在后续对设备的操作中,
只要引用新的设备名就可以了。但为了保证最大限度的兼容,一般来说,
新设备名总是作为一个对内核自动产生的设备名的符号链接(link)来使用的。
   
例如:内核产生了sda设备名,而根据信息,这个设备对应于是我的内置硬盘,那我就可以制定udev规则,让udev除了产生/dev/sda设备文件
外,另外创建一个符号链接叫/dev/internalHD。这样,我在fstab文件中,就可以用/dev/internalHD来代替原来的
/dev/sda了。下次,由于某些原因,这个硬盘在内核中变成了sdb设备名了,那也不用着急,udev还会自动产生/dev/internalHD这
个链接,并指向正确的/dev/sdb设备。所有其他的文件像fstab等都不用修改。
     而在在2.6内核以前一直使用的是
devfs,devfs挂载于/dev目录下,提供了一种类似于文件的方法来管理位于/dev目录下的所有设备,但是devfs文件系统有一些缺点,例
如:不确定的设备映射,有时一个设备映射的设备文件可能不同,例如我的U盘可能对应sda有可能对应sdb 。
注:可以用命令查看其中的信息,    udevinfo -a -p /sys/block/sda

Sysfs文件系统与Linux设备模型的更多相关文章

  1. Linux设备模型——设备驱动模型和sysfs文件系统解读

    本文将对Linux系统中的sysfs进行简单的分析,要分析sysfs就必须分析内核的driver-model(驱动模型),两者是紧密联系的.在分析过程中,本文将以platform总线和spi主控制器的 ...

  2. linux设备模型_转

    建议原博文查看,效果更佳. 转自:http://www.cnblogs.com/wwang/category/269350.html Linux设备模型 (1) 随着计算机的周边外设越来越丰富,设备管 ...

  3. Linux设备模型:基础篇

    linux提供了新的设备模型:总线(bus).设备(device).驱动(driver).其中总线是处理器与设备之间通道,在设备模型中,所有的设备都通过总线相连:设备是对于一个设备的详细信息描述,驱动 ...

  4. Linux设备模型(热插拔、mdev 与 firmware)【转】

    转自:http://www.cnblogs.com/hnrainll/archive/2011/06/10/2077469.html 转自:http://blog.chinaunix.net/spac ...

  5. Linux设备模型 (1)

    随着计算机的周边外设越来越丰富,设备管理已经成为现代操作系统的一项重要任务,这对于Linux来说也是同样的情况.每次Linux内核新版本的发布,都会伴随着一批设备驱动进入内核.在Linux内核里,驱动 ...

  6. Linux 设备模型

    在 2.5 开发循环中一个声明的目标是为内核创建一个统一的设备模型. 之前的内核没有单一的数据结 构, 使它们可以来获取关于系统如何整合的信息. 尽管缺乏信息, 有时事情也进行的不错. 新系统, 带 ...

  7. Linux设备模型之kobject

    阿辉原创,转载请注明出处 参考文档:LDD3-ch14.内核文档Documentation/kobject.txt,本文中使用到的代码均摘自Linux-3.4.75 ----------------- ...

  8. 【原创】linux设备模型之kset/kobj/ktype分析

    背 景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本 ...

  9. Linux设备模型(总线、设备、驱动程序和类)

    Linux设备驱动程序学习(13) -Linux设备模型(总线.设备.驱动程序和类)[转] 文章的例子和实验使用<LDD3>所配的lddbus模块(稍作修改). 提示:在学习这部分内容是一 ...

随机推荐

  1. 64_l2

    libcec-devel-4.0.2-3.fc26.x86_64.rpm 22-May-2017 22:13 27942 libcephfs-devel-10.2.7-2.fc26.i686.rpm ...

  2. 如何使用vux创建vue项目

    1.安装vue-cli,通过vue-v可以查明 安装vue-cli步骤 vue init airyland/vux2 projectPath(项目名字) 2.安装依赖模块 方法1:npm instal ...

  3. Search for a Range——稍微升级版的二分查找

    Given a sorted array of integers, find the starting and ending position of a given target value. You ...

  4. matlab实用命令

    实用命令 打点测时 在需要测量的开始部分标记: tic 在需要测量的结束部分标记: toc 记录程序从tic到toc运行所花费的时间 Image 翻转 fliplr(x) //左右翻转 flipud( ...

  5. SnagIt截图后无法在编辑器打开,不显示截图内容的解决办法(转)

    方法1: 用SnagIt截图后,弹出的编辑器里不显示刚才截图的内容,解决办法如下: 完全退出Snagit和编辑器,删除以下文件夹: Win7用户 C:\Users\Administrator\AppD ...

  6. EF Groupby

    最近做了个检索类的项目,其中就用到统计了,就是按照热门搜索排序来的. 话不多说,直接代码 var requirementSearchesOrder = app_RequirementSearches. ...

  7. (翻译)Xamarin.Essentials 最新预览版的更多跨平台 API

    原文地址:https://blog.xamarin.com/cross-platform-apis-xamarin-essentials-latest-preview/ 在 Microsoft Bui ...

  8. Druid数据迁移小计

    Druid数据迁移小计 Druid 官方网站上讲了相关的 Dump Segment 和 Insert Segment 相关的功能,但是经过测试这些功能都不好用,报 Guice 的依赖错误,懒得找具体原 ...

  9. 【转载】TabLayout 源码解析

    原文地址:https://github.com/Aspsine/AndroidSdkSourceAnalysis/blob/master/article/TabLayout%E6%BA%90%E7%A ...

  10. 洛谷P3620 [APIO/CTSC 2007] 数据备份 [堆,贪心,差分]

    题目传送门 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽 ...