Sysfs之我见

sysfs虚拟文件系统提供了一种比proc更理想的访问内核数据的途径。

1
2
3
4
5
6
7
8
_______ _______ _______ _______
( ____ \|\ /|( ____ \( ____ \( ____ \
| ( \/( \ / )| ( \/| ( \/| ( \/
| (_____ \ (_) / | (_____ | (__ | (_____
(_____ ) \ / (_____ )| __) (_____ )
) | ) ( ) || ( ) |
/\____) | | | /\____) || ) /\____) |
\_______) \_/ \_______)|/ \_______)

1.sysfs的目录结构

sysfs总是挂载在/sys文件夹上。
在/sys目录下一般有block、bus、class、dev、devices、firmware、fs、kernel、module、power等目录。

  • /sys/devices: 这是内核对系统中所有设备的分层次表达模型,也是 /sys 文件系统管理设备的最重要的目录结构。
  • /sys/dev: 这个目录下维护一个按字符设备和块设备的主次号码(major:minor)链接到真实的设备(/sys/devices下)的符号链接文件。
  • /sys/bus: 这是内核设备按总线类型分层放置的目录结构, devices 中的所有设备都是连接于某种总线之下,在这里的每一种具体总线之下可以找到每一个具体设备的符号链接,它也是构成 Linux 统一设备模型的一部分。
  • /sys/class:这是按照设备功能分类的设备模型,如系统所有输入设备都会出现在 /sys/class/input 之下,而不论它们是以何种总线连接到系统。
  • /sys/block: 这里是系统中当前所有的块设备,具体链接到devices下的具体设备。
  • /sys/firmware:这里是系统加载固件机制的对用户空间的接口,如设备树的各个分层都位于这个文件夹下。
  • /sys/fs:这里按照设计是用于描述系统中所有文件系统,包括文件系统本身和按文件系统分类存放的已挂载点。如当前的Linux系统中存在ext4文件系统,该目录下就会存在ext4目录。
  • /sys/kernel:这里是内核所有可调整参数的位置,目前只有 uevent_helper, kexec_loaded, mm, 和新式的 slab 分配器等几项较新的设计在使用它,其它内核可调整参数仍然位于 sysctl (/proc/sys/kernel) 接口中。
  • /sys/module: 这里有系统中所有模块的信息,不论这些模块是以内联(inlined)方式编译到内核映像文件(vmlinuz)中还是编译为外部模块(ko文件),都可能会出现在 /sys/module 中。
  • /sys/power: 这里是系统中电源选项,这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机、重启等。

2.udev使用

2.1 udev工作过程:

  当内核检测到在系统中出现了新设备后(产生hotplug事件),内核会在sysfs文件系统中为该新设备生成一项新的记录,一般sysfs文件系统会被mount到/sys目录中。新记录是以一个或多个文件或目录的方式来表示。每个文件都包含有特定的信息。udev在系统中是以守护进程的方式udevd在运行。检测到新设备的出现,通过查找设备对应的sysfs中的记录得到设备的一些信息。udev会根据/etc/udev/udev.conf文件中的udev_rules指定的目录,逐个检查该目录下的文件,这个目录下的文件都是针对某类或某个设备应该施行什么措施的规则文件。udev读取文件是按照文件名的ASCII字母顺序来读取的,如果udev一旦找到了与新加入的设备匹配的规则,udev就会根据规则定义的措施对新设备进行配置。同时不再读后续的规则文件。

2.2 udev规则

2.2.1 规则的所有操作符

  • “==”:  比较键、值,若等于,则该条件满足;
  • “!=”:   比较键、值,若不等于,则该条件满足;
  • “=”:    对一个键赋值;
  • “+=”:  为一个表示多个条目的键赋值。
  • “:=”:  对一个键赋值,并拒绝之后所有对该键的改动。目的是防止后面的规则文件对该键赋值。

2.2.2 规则的匹配键

  • ACTION:          事件 (uevent) 的行为,例如:add( 添加设备 )、remove( 删除设备 )。
  • DEVPATH:        设备的 devpath 路径。
  • SUBSYSTEM:        设备的子系统名称,例如:sda 的子系统为 block。
  • BUS:            设备在 devpath 里的总线名称,例如:usb。
  • DRIVER:           设备在 devpath 里的设备驱动名称,例如:ide-cdrom。
  • ID:             设备在 devpath 里的识别号。
  • SYSFS{filename}:     设备的 devpath 路径下,设备的属性文件“filename”里的内容。例如:SYSFS{model}==“ST936701SS”表示:如果设备的型号为 ST936701SS,则该设备匹配该 匹配键。在一条规则中,可以设定最多五条 SYSFS 的 匹配键。
  • ENV{key}:          环境变量。在一条规则中,可以设定最多五条环境变量的 匹配键。
  • PROGRAM:        调用外部命令。
  • RESULT:          外部命令 PROGRAM 的返回结果。

2.2.3 重要赋值键

  • NAME:           在 /dev下产生的设备文件名。只有第一次对某个设备的 NAME 的赋值行为生效,之后匹配的规则再对该设备的 NAME 赋值行为将被忽略。如果没有任何规则对设备的 NAME 赋值,udev 将使用内核设备名称来产生设备文件。
  • SYMLINK:          为 /dev/下的设备文件产生符号链接。由于 udev 只能为某个设备产生一个设备文件,所以为了不覆盖系统默认的 udev 规则所产生的文件,推荐使用符号链接。
  • OWNER, GROUP, MODE:  为设备设定权限。
  • ENV{key}:         导入一个环境变量。

2.2.4 值和可调用的替换操作符

  • $kernel, %k:        设备的内核设备名称,例如:sda、cdrom。
  • $number, %n:        设备的内核号码,例如:sda3 的内核号码是 3。
  • $devpath, %p:        设备的 devpath路径。
  • $id, %b:           设备在 devpath里的 ID 号。
  • $sysfs{file}, %s{file}:  设备的 sysfs里 file 的内容。其实就是设备的属性值。
  • $env{key}, %E{key}:    一个环境变量的值。
  • $major, %M:         设备的 major 号。
  • $minor %m:         设备的 minor 号。
  • $result, %c:        PROGRAM 返回的结果。
  • $parent, %P:       父设备的设备文件名。
  • $root, %r:         udev_root的值,默认是 /dev/。
  • $tempnode, %N:       临时设备名。
  • %%:             符号 % 本身。
  • $$:             符号 $ 本身。

2.3 udev使用

假设一个USB扫描仪每次插入Linux设备名称都会变,那么就可以使用:

1
2
3
4
SYSFS{idVendor}=="0686", \
SYSFS{idProduct}=="400e", \
SYMLINK+="scanner", MODE="0664", \
group="scanner"

前两行,确定了扫描仪的生产商和产品号,那么在每次重新插入的时候,都会创建一个/dev/scanner的符号连接,访问权限设置为0664。

修改U盘名称:

1
KERNEL=="sdc4",SUBSYSTEMS=="block", NAME+="kinstonusb",SYMLINK+="kinstonusb_link"

比如你的sdc的优盘为金士顿的,但系统会识别成sdc4不易于识别,那么就可以对sdc建立一个kinstonusb_link链接。

版权声明:本文为博主原创文章,转载需声明为转载内容并添加原文地址。

原文地址:http://coderdock.com

Dock wechat
欢迎您扫一扫上面的微信公众号,订阅我的公众号