转: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. HDU 5129 Yong Zheng's Death

    题目链接:HDU-5129 题目大意为给一堆字符串,问由任意两个字符串的前缀子串(注意断句)能组成多少种不同的字符串. 思路是先用总方案数减去重复的方案数. 考虑对于一个字符串S,如图,假设S1,S2 ...

  2. 图论-最近公共祖先-离线Tarjan算法

    有关概念: 最近公共祖先(LCA,Lowest Common Ancestors):对于有根树T的两个结点u.v,最近公共祖先表示u和v的深度最大的共同祖先. Tarjan是求LCA的离线算法(先存储 ...

  3. python一步高级编程

    1.==,is的使用 总结 ·is是比较两个引用是否指向了同一个对象(引用比较). ·==是比较两个对象是否相等. 2.深拷贝.浅拷贝 1.浅拷贝 浅拷贝是对于一个对象的顶层拷贝 通俗的理解是:拷贝了 ...

  4. ueditor在QQ浏览器或者IE浏览器中无法加载

    因为IE浏览器有兼容问题,打开网址,浏览器不一定以最新的文档模式加载.按F12查看 在你网址的head标签中加入:<meta http-equiv="x-ua-compatible&q ...

  5. linux命令(34):less命令

    1.命令格式: less [参数]  文件 2.命令功能: less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会 ...

  6. 181. Employees Earning More Than Their Managers

    The Employee table holds all employees including their managers. Every employee has an Id, and there ...

  7. 无法使用命令 /usr/bin/xdpyinfo 自动检查显示器颜色。请检查是否设置了 DISPLAY

    https://blog.csdn.net/woshigedahaoren/article/details/9493887

  8. Aras Innovator 11 sp2 firefox客户端设置

    在上一篇文章<Aras Innovator 11 sp2 安装>后,服务器算是安装好了,还需要在使用的客户端进行设置才可以正常使用Aras Innovator 该篇为firefox设置,还 ...

  9. http.pieplining

    默认情况下http协议中每个传输层连接只能承载一个http请求和响应,然后结束. HTTP是一个简单的协议.客户进程建立一条同服务器进程的 T C P连接,然后发出请求并读取服务器进程的响应.服务器进 ...

  10. VS2013下实现移动端的跨平台开发

    http://www.th7.cn/Program/Android/201412/336394.shtml 前一天准备下载VS2015预览版,到VisualStudio官网一看,发现微软发布了Visu ...