Linux sysfs III

sysfs是一个基于ramfs的文件系统,在2.6内核开始引入,用来导出内核对象(kernel object)的数据、属性到用户空间。与同样用于查看内核数据的proc不同,sysfs只关心具有层次结构的设备信息,比如系统中的总线,驱动以及已经加载的模块等,而诸如PID等信息还是使用proc来管理。本质上,sysfs文件的层次结构就是基于内核中kset与kobject逻辑结构来组织的。从驱动开发的角度,/sysfs为我们提供了除了设备文件/dev/proc之外的另外一种通过用户空间访问内核数据的方式。想要使用sysfs,编译内核的时候需要定义CONFIG_SYSFS,可以通过mount -t sysfs sysfs /sys命令来挂载sysfs到“/sys”目录。本文以ubuntu15.04(3.19)为例分析。

/sys

sysfs的布局体现内核的数据结构,顶层的目录有

$ls /sys/
block/  bus/  class/  dev/  devices/  firmware/  fs/  hypervisor/  kernel/  module/  power/

其中 “sys/class/”,”sys/bus/”,”sys/devices”是设备开发中最重要的几个目录。他们之间的关系可以用下图表示。

每一个目录都对应内核中的一个kset,每一个kset还会包含一些kobject或其他kset。下面针对常用目录做一个简单的介绍

Continue reading

Linux sysfs II

本文聚焦于sysfs Inside Tree的另一个层次的问题:对总线设备的描述和管理。对设备的管理,主要集中于sysfs Inside Tree中的5个概念:device,bus,driver,class和interface,本文也围绕这几个概念展开。

在硬件系统中,计算机通过形形色色的总线将设备组织成一个树状结构,这棵树的根就是CPU核。在软件的世界,同样有一棵树用于描述硬件信息。很容易想到,软件拓扑要严格的对应硬件结构才会清晰易懂,但是易懂并不是设备管理的目标(至少不是唯一的目标),所以实际的Device Driver子系统在此基础上充分发挥了代码重用,面向对象,合理的数据结构等设计方式,使整个Device Driver子系统既保持了与硬件变化相适配的软件数据结构,又提供了高效的管理与驱动方式。

当我们说一个总线的时候,其硬件实质就是一个”控制器+线”,而这个控制器又是挂载到另外一个总线(Parent)上的,所以如果站在另外一条总线(Parent)上看,这条总线又是一个Device,既然是Device,那么是要有对应的Driver来存储诸如硬件寄存器读写等驱动方法… ,所以,在Device Driver 子系统中,Bus,Device Driver并不是完全独立的,而是你中有我,我中有你的关系。无论是什么关系,显然,他们在内核中都是作为对kobject的再次封装,服从sysfs的组织和管理。 

bus_type

Continue reading

Linux sysfs I

kernel管理的设备千差万别,但最终都归于统一设备模型的管理, 即sysfs,理解了sysfs,就可以管窥蠡豹,对整个DeviceDriver子系统有一个清晰的认识。sysfs的实质是以文件系统的形式展示内核中的Device Driver信息,因此,理解sysfs可以分为2个维度的问题:

  • sysfs的Inside Tree的组织思想
  • sysfs的Outside Tree的目录结构

本文主要讨论内部树的基础,kobject,kset和ktype的定义联系及其常用API

kobject

list_head是内核所有链式存储数据结构的基础,可以看作这些struct的父类,基于同样的思想,在Device Driver Subsystem中, 这个全局父类的角色由kobject担任,当然,kobject本身也是一个list_head的子类。kobject为Device Driver管理的对象提供了最高层次的抽象,无论是Device对象还是Driver对象,都可以看作kobject的父类,sysfs通过kobject,就可以管理系统中所有的Device对象和Driver对象。

//include/linux/kobject.h
 63 struct kobject { 
 64         const char              *name;
 65         struct list_head        entry;
 66         struct kobject          *parent;
 67         struct kset             *kset;
 68         struct kobj_type        *ktype;
 69         struct kernfs_node      *sd;
 70         struct kref             kref;
 71 #ifdef CONFIG_DEBUG_KOBJECT_RELEASE
 72         struct delayed_work     release;
 73 #endif
 74         unsigned int state_initialized:1;
 75         unsigned int state_in_sysfs:1;
 76         unsigned int state_add_uevent_sent:1;
 77         unsigned int state_remove_uevent_sent:1;
 78         unsigned int uevent_suppress:1;
 79 };

–64–>kobject对象的名字
–65–>kobject对象之间的连接件
–66–>该kobject对象的父kobject对象
–67–>该kobject所属的kset
–68–>该kobject附属的ktype
–69–>该kobject在sysfs中的形式,比如符号链接,目录以及属性等信息
–70–>引用计数成员,本质是一个原子变量,用于决定何时释放对象
–74–>1bit,如果该kobject对象已经被初始化,则为1
–75–>1bit,如果该kobject对象已经被添加到sysfs中,则为1
–76–>1bit,如果该kobject对象已经发送过uevent add事件到用户空间,则为1
–77–>1bit,如果该kobject对象已经发送过uevent remove事件到用户空间,则为1
–78–>1bit,如果该kobject对象”抑制”发送事件到用户空间,则为1

kobj_init()

Continue reading