1. /sys/目录:
在Linux系统中,/sys目录是一个虚拟文件系统,用于提供对内核数据结构的访问接口。它包含了大量的子目录和文件,每个子目录和文件都对应着内核中的一个数据结构或者控制接口。下面是一些常见的子目录及其作用:
- /sys/block:用于管理块设备(如硬盘、U盘等),包括设备的大小、分区、挂载等信息。
- /sys/bus:用于管理总线,比如PCI、USB等。
- /sys/class:用于管理设备的类型,比如输入设备、声卡、网络设备等。
- /sys/devices:用于管理物理设备,包括CPU、内存、硬盘、网卡等。
- /sys/fs:用于管理文件系统,包括各种文件系统的挂载点、属性等信息。
- /sys/kernel:用于管理内核参数、模块、时间等。
- /sys/power:用于管理系统的电源状态。
- /sys/virtual:用于管理虚拟设备,比如虚拟网卡、虚拟文件系统等。 通过读取和修改这些子目录和文件,可以实现对系统各种资源的管理和调整。
sysfs组织结构,进入sysfs目录中。有block bus class dev devices firmware fs kernel module power这些目录。具体代表看名字差不多就可以看出。在层次结构上,假如有一个设备A。将有一个名称为A的目录。A设备是在B总线上。那A设备应该在bus目录下的B总线下
2. 基类目录:
sys目录下首先有些基目录,比如iic、pci啥的,这些基目录实则在驱动代码中对照着一个Kset集合,大概长这个亚子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
这里面内嵌了一个“struct kobject kobj”,这里不是指针,是包含,所包含的东西就是基类,比如iic、pci这种,以后的每个“struct kobject kobj”结构都会关联这个kset,表示层次默认在此基类之下,即每个“struct kobject kobj”对应的目录应该默认是基目录的子目录
可以理解为kset是一个顶层容器
kset链表中的kobject对象的parent指针一般都指向kset内嵌的kobject对象
kset_uevent_ops是热插拔事件:
热插拔事件是用内核空间发送到用户空间的通知。表明内核中的某些配置已经发生变化。用户空间则会根据这些信息做相应的处理。例如,U盘插入USB系统时,会产生一个热插拔事件,内核会捕捉到这个热插拔事件,然后调用/sbin/hotplug程序,该程序通知加载驱动程序来相应U盘的插入动作。
热插拔函数集的定义在include/linux/koject.h中
3. 驱动设备目录:
每个在内核中注册的kobject都对应于sysfs文件系统中的一个目录,一般肯定是在基目录之下的,kobject长这个亚子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
里面有很多东西都是关联(指针)而不是包含(内嵌),比如kset、parent、ktype,表明这个结构层次并非在这些指向结构之上,
parent指针:也是同一种类型,如果这个父指针指向了一个具体的kobj,那么会代表着在实际目录中就会在这个父目录之下
kset指针:如果上一个指针没有指向具体的父指针,那么好了,本结构对应的目录就要位于基目录之下了,如果父指针指定了,那么就按照parent的指向来
ktype指针:这个表示这个结构的一些特性,这种特性或许是独一无二的,或许是很普遍的
sd指针:指向了sysfs_dirent结构体,改结构体在sysfs中表示的就是这个kobject,从sysfs文件系统内部看来,这个结构表示kobject的一个inode结构体
4. 对象属性:
长这个亚子:
1 2 3 4 5 |
|
其中包含了文件操作函数,这个只有读和写
还包含了属性数组指针,可以有丰富的属性条目
1 2 3 4 5 6 7 8 9 |
|
5. 字符设备举例:
1 2 3 4 5 6 7 8 |
|
比如字符设备的结构里面就是包含了这样一个“struct kobject kobj”结构,即本字符设备包括了sys文件目录中的资源
6. pci举例
在此设备中包含了:
1 2 3 4 5 6 7 8 |
|
即一个pci插槽包含了一个这样的“struct kobject kobj”结构
6.1. pci设备文件系统扩展:
在Linux的PCI文件系统中,/sys/device/pci目录下的每个设备子目录都包含了该设备的资源信息,其中包括了该设备所使用的所有BAR(Base Address Register)的相关信息。每个BAR都代表了设备在地址空间中所占用的一段内存或者IO空间。
在/sys/device/pci/<bus>/<dev>.<func>/resource文件中,可以找到该设备所使用的所有BAR的地址范围信息。
而在/sys/device/pci/<bus>/<dev>.<func>/resourceX(其中X为对应的BAR号)文件中,则包含了该BAR所代表的地址范围的具体信息,如地址起始位置、大小、寻址方式等。
因此,可以通过在/sys/device/pci目录下查找相应设备的resource文件和对应的resourceX文件,来确定该设备所使用的所有BAR的相关信息。
7. IIC步骤:
在Linux系统中,I2C设备通常会被挂载到/sys/bus/i2c/devices目录下。
这个目录下的每个子目录都代表着一个I2C设备,其名称为设备的I2C地址。
7.1. 步骤:
1. 在设备树中添加I2C设备节点,并指定设备的I2C地址和总线编号。
2. 在驱动程序中实现I2C设备的注册和初始化,并创建相应的设备节点。
3. 将设备节点挂载到/sys/bus/i2c/devices目录下,以便用户空间程序可以访问设备。
7.2. 数据结构
在实际实现中,可以使用sysfs_create_link()函数来创建设备节点,并使用sysfs_create_dir()函数来创建I2C设备目录。
同时,还需要在驱动程序中实现read()和write()等文件操作方法,以便用户空间程序可以通过/sys接口来访问设备。
sysfs_create_link()函数的作用是在/sys目录下创建一个符号链接文件,用于将一个设备节点链接到另一个设备节点。 这个函数的参数包括要创建的符号链接文件的路径、目标设备节点的路径和目标节点的名称。
sysfs_create_dir()函数的作用是在/sys目录下创建一个新的子目录。这个函数的参数包括要创建的子目录的路径和名称。
创建成功后,可以在这个子目录下创建新的设备节点,以便用户空间程序可以访问设备。 这两个函数在Linux系统中常用于驱动程序的实现中,用于创建设备节点和设备目录,以便用户空间程序可以通过/sys接口来访问设备。 需要注意的是,在使用这两个函数时,需要确保当前用户具有足够的权限来创建和访问/sys目录下的文件和目录。
关键转换在这里:
1 2 3 4 5 |
|
在Linux内核中,I2C设备通常会被表示为一个i2c_client结构体。
这个结构体包含有关设备的信息,例如设备的名称、I2C地址、总线编号等。
同时,这个结构体也包含了一个指向设备驱动程序的指针,以便在发生I2C传输时可以调用相应的驱动程序。
另一方面,Linux内核中还包含了一个kobject结构体,用于表示内核对象。 这个结构体包含了一些基本的信息,例如对象的名称、父对象、引用计数等。
同时,这个结构体还包含了一些回调函数指针,用于实现对象的一些操作,例如创建、销毁、属性访问等。 在Linux系统中,i2c_client结构体通常会通过kobject结构体进行管理。
具体来说,每个i2c_client结构体都会被表示为一个kobject结构体,并且将其添加到/sys/bus/i2c/devices目录下,以便用户空间程序可以访问设备。
同时,这个kobject结构体还可以添加一些属性,例如设备的状态、版本号等,以便用户空间程序可以查询设备的状态信息。
因此,可以说i2c数据结构和kobject的交集就在于它们都用于表示Linux内核中的对象,并通过/sys文件系统提供接口,以便用户空间程序可以访问和管理这些对象。
同时,kobject结构体还提供了一些额外的功能,例如属性访问、事件通知等,可以帮助驱动程序实现更复杂的操作。