总结
根据之前的kobject知道 /sys/目录下的每个文件夹都是一个 kobject的对象
使用class_create() 创建 /sys/class/xxx目录 同时返回class对象
使用device_create() 创建/sys/class/xxx/yyy目录 和创建/dev/yyy的文件节点 同时返回device对象
class和device 都间接继承于kobject 所以kobject是总线、驱动、设备的三种对象的一个基类
细节分析
uevent机制
用户空间和内核沟通的桥梁
在linux内核空间使用kobject_uevent()函数 konject对象发送信息到 用户空间的udev或mdev守护进程
udev或mdev守护进程解析发过来的包 根据规则进行相应操作
如上图中 device_create的时候创建了device对象(间接继承于kobject结构体)
所以device对象有目录在 /sys/文件夹下 同时使用kobject_uevent() 让用户空间创建/dev/yyy文件节点
class 设备大管家
在系统启动的初期就会有文件夹 /sys/class
下面看看是怎么创建出来的
init/main.c里:
kernel_init
->kernel_init_freeable
->do_basic_setup
->driver_init
这是driver_init函数:创建各种kobject对象 在/sys/下映射各种目录
void __init driver_init(void)
{
/* These are the core pieces */
devtmpfs_init();
devices_init();/*device、dev目录*/
buses_init();/*bus目录*/
classes_init();/*class目录*/
firmware_init();/*firmware目录*/
hypervisor_init();/*hypervisor目录*/
/* These are also core pieces, but must come after the
* core core pieces.
*/
platform_bus_init();
cpu_dev_init();
memory_dev_init();
container_dev_init();
of_core_init();
}
下面来看看平时常用的 probe成功后调用的两个函数 class_create device_create 都干了什么
class_create()
/sys/class目录 对硬件设备进行管理
和udev守护进程进行协作,自动创建设备节点 以前创建设备节点需要在用户空间手动mknode
class_create()创建目录 /sys/class/xxx 同时返回class对象
device_create()创建目录 创建/sys/class/xxx/yyy目录 同时返回device对象
虽然class_create() 和 device_create() 都能创建目录项
但device_create()不止创建了 /sys/class/xxx/yyy 还在yyy目录下创建了属性文件(/sys/class/xxx/yyy/dev)
属性文件记录硬件设备的设备号
创建完属性文件后 继续使用kobject_uevent()发送驱动添加的消息 给用户空间的udev守护进程
这是udev会找到创建的yyy 读取dev这个设备属性文件夹 获得硬件设备的设备号
udev 调用mknod()函数 来创建/dev/yyy的设备节点
class_create()函数分析
调用这个函数的本质是创建一个新的kobject对象 kobject对象映射目录文件为/sys/class/xxx/
同时返回的class结构体 class结构体是有间接继承kobject的对象
class_create(owner, name)
__class_create(owner, name, &__key);
owner:一般设置为THIS_MODULE
name:kobject对象的名字
device_create()函数
返回的device结构体 也间接继承了kobject对象
device *device_create(struct class *class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt, ...)
- class:新构建的class
- parent:新kobject对象的上一层节点,一般为NULL
- dev_t:属性文件记录该设备号
- drvdata:私有数据,一般为NULL
- fmt:变参参数,一般用来设置kobject对象的名字