linux驱动结构
来源:互联网 发布:数据决策分析系统 编辑:程序博客网 时间:2024/06/04 18:55
kobject
->kobject *parent
->kset
->struct list_head //指向了所包含的kobject的链表头
->struct kobject kobj
->kobj_type
->void (*release) (struct kobject *kobj)
->struct sysfs_ops *sysfs_ops;
....
(1).kobject如果没有指定父节点,parent将指向kset内嵌的kobject。
(2)每个kobject都有它的kobj_type字段指针,用来表示kobject在文件系统中
的操作方法。relase方法是在kobject释放时调用,sysfs_ops指向kobject
对应的文件操作,default_attrskobject的默认属性,sysfs_ops将使用这
个属性。
一、kobject在内核的结构:
(1)kobject_create_and_add()函数创建kobject,挂到父kobject,并设置其kobj_type,在文件系统中为其创建目录和属性文件等。
kobject_create_and_add()
->kobject_create()
->kobject_init()
->kobject_init_internal()
->kobject_add()
->kobject_add_varg()
->kobject_set_name_vargs(kobj, fmt, vargs)
->kvasprintf()
->kobject_add_internal()
->kobject_get(kobj->parent);
->create_dir(kobj)
->sysfs_create_dir(kobj);
->populate_dir(kobj)
->sysfs_remove_dir(kobj)
函数说明:
kobject_create_and_add()接口函数,kobject添加到文件系统中去(实际上是添加到其父节点所代表的kset中去)
kobject_create()为要创建的kobject分配内存空间并对其初始化.
kobject_init()对kobject基本字段进行初始化,用输入参数设置kobj_type属性.
kobject_add_varg中将把fmt指向的内容赋给kobject的name字段。
kobject_set_name_vargs(kobj, fmt, vargs),如果kobj的name字段指向的内容为空,则为分配一个内存空间并用fmt指向的内容初始化,把地址赋给kobj的name字段。
kobject_add_varg()返回kobject_add_internal(kobj),就是在这个函数理为kobj创建文件系统结构
kobject_add_internal()检查kobj和它的name字段,不存在则返回错误信息
arent = kobject_get(kobj->parent);获得其父节点,并增加父节点的计数器,kobject结构中的 kref字段用于容器的计数,kobject_get和kobject_put分别 增加和减少计数器,如果计数器为0,则释放该kobject, kobject_get返回该kobject。
create_dir()函数中具体创建了那些内容
sysfs_create_dir()先为kobj创建了一个目录文件
如果kobj->parent为NULL,就把&sysfs_root作为父节点sd,即在/sys下面创建结点。
populate_dir:然后调用
由于上面kobject_init(kobj, &dynamic_kobj_ktype)用默认dynamic_kobj_ktype作为kobj_type参数,而dynamic_kobj_ktype的default_attrs为NULL,所以这里没有创建属性文件。
至此,我们已经知道了kobject_create_and_add()函数创建kobject,挂到父kobject,并设置其kobj_type,在文件系统中为其创建目录和属性文件等。
另外,如果我们已静态定义了要创建的kobject,则可以调用kobject_init_and_add()来注册kobject
int kobject_init_and_add()
(2)我们已静态定义了要创建的kobject,则可以调用kobject_init_and_add()来注册kobject
(3)内核提供注销kobject的函数是kobject_del()
二、kset在内核中的结构:
(1)内核同样提供了创建和注册kset的函数kset_create_and_add()
->先调用kset_create ()创建一个kset,接着调用kset_register()注册它
->kset_create()中kset内嵌的kobject(这里还未将kobject注册到文件系统),另外用输入参数初始化kset的uevent_ops字段。
->kset_register()调用kobject_add_internal()将kset内嵌的kobject注册到文件系统, 这个函数我们在上面已经分析。
->注册kset会产生一个事件,就是在这里调用了kobject_uevent(&k->kobj, KOBJ_ADD)
->如果kobj的kset和parent字段都不存在,说明找不到所属kset,也就没有 uevent_ops,不能产生事件,返回错误信息;相反则找到了存在kset的kobj 或父kobject(依次往上找),并赋值给uevent_ops。
->add_uevent_var()kobj_uevent_env填充action_string,kobject路径, 子系统名称以及其他指定环境变量
->调用uevent_ops的uevent函数,编程人员可在此函数中实现自定义的 功能。
->设置KOBJ_ADD和KOBJ_REMOVE的标志。
->添加HOME和PATH环境变量。
->调用hotplug函数。
(2)kset_unregister() 减少其内嵌的kobj计数,为0则释放其内存空间。
常用函数:
1 #define MKDEV(major,minor) (((major) << MINORBITS) | (minor)) 将主设备号和次设备号转换成 dev_t类型
2 struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
相关的几个接口:
->LIST_HEAD()
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
常见函数:
cdev_alloc(void)
-> kzalloc(sizeof(struct cdev), GFP_KERNEL)
->INIT_LIST_HEAD(&p->list)
->kobject_init(&p->kobj, &ktype_cdev_dynamic)
cdev_init(...)
->INIT_LIST_HEAD(&cdev->list)
->kobject_init(&cdev->kobj, &ktype_cdev_default)
->cdev->ops = fops;
cdev_add(...)
->kobj_map(...) kobj_map 结构的 cdev_map 变量中包含一个散列表用来快速存取所有的对象。
kobj_map() 函数就是用来把字符设备编号和 cdev 结构变量一起保 存到 cdev_map 这个散列表里。当后续要打开一个字符设备文件时, 通过调用 kobj_lookup() 函数,根据设备编号就可以找到 cdev 结 构变量,从而取出其中的 ops 字段。
->kobject *parent
->kset
->struct list_head //指向了所包含的kobject的链表头
->struct kobject kobj
->kobj_type
->void (*release) (struct kobject *kobj)
->struct sysfs_ops *sysfs_ops;
....
(1).kobject如果没有指定父节点,parent将指向kset内嵌的kobject。
(2)每个kobject都有它的kobj_type字段指针,用来表示kobject在文件系统中
的操作方法。relase方法是在kobject释放时调用,sysfs_ops指向kobject
对应的文件操作,default_attrskobject的默认属性,sysfs_ops将使用这
个属性。
一、kobject在内核的结构:
(1)kobject_create_and_add()函数创建kobject,挂到父kobject,并设置其kobj_type,在文件系统中为其创建目录和属性文件等。
kobject_create_and_add()
->kobject_create()
->kobject_init()
->kobject_init_internal()
->kobject_add()
->kobject_add_varg()
->kobject_set_name_vargs(kobj, fmt, vargs)
->kvasprintf()
->kobject_add_internal()
->kobject_get(kobj->parent);
->create_dir(kobj)
->sysfs_create_dir(kobj);
->populate_dir(kobj)
->sysfs_remove_dir(kobj)
函数说明:
kobject_create_and_add()接口函数,kobject添加到文件系统中去(实际上是添加到其父节点所代表的kset中去)
kobject_create()为要创建的kobject分配内存空间并对其初始化.
kobject_init()对kobject基本字段进行初始化,用输入参数设置kobj_type属性.
kobject_add_varg中将把fmt指向的内容赋给kobject的name字段。
kobject_set_name_vargs(kobj, fmt, vargs),如果kobj的name字段指向的内容为空,则为分配一个内存空间并用fmt指向的内容初始化,把地址赋给kobj的name字段。
kobject_add_varg()返回kobject_add_internal(kobj),就是在这个函数理为kobj创建文件系统结构
kobject_add_internal()检查kobj和它的name字段,不存在则返回错误信息
arent = kobject_get(kobj->parent);获得其父节点,并增加父节点的计数器,kobject结构中的 kref字段用于容器的计数,kobject_get和kobject_put分别 增加和减少计数器,如果计数器为0,则释放该kobject, kobject_get返回该kobject。
create_dir()函数中具体创建了那些内容
sysfs_create_dir()先为kobj创建了一个目录文件
如果kobj->parent为NULL,就把&sysfs_root作为父节点sd,即在/sys下面创建结点。
populate_dir:然后调用
由于上面kobject_init(kobj, &dynamic_kobj_ktype)用默认dynamic_kobj_ktype作为kobj_type参数,而dynamic_kobj_ktype的default_attrs为NULL,所以这里没有创建属性文件。
至此,我们已经知道了kobject_create_and_add()函数创建kobject,挂到父kobject,并设置其kobj_type,在文件系统中为其创建目录和属性文件等。
另外,如果我们已静态定义了要创建的kobject,则可以调用kobject_init_and_add()来注册kobject
int kobject_init_and_add()
(2)我们已静态定义了要创建的kobject,则可以调用kobject_init_and_add()来注册kobject
(3)内核提供注销kobject的函数是kobject_del()
二、kset在内核中的结构:
(1)内核同样提供了创建和注册kset的函数kset_create_and_add()
->先调用kset_create ()创建一个kset,接着调用kset_register()注册它
->kset_create()中kset内嵌的kobject(这里还未将kobject注册到文件系统),另外用输入参数初始化kset的uevent_ops字段。
->kset_register()调用kobject_add_internal()将kset内嵌的kobject注册到文件系统, 这个函数我们在上面已经分析。
->注册kset会产生一个事件,就是在这里调用了kobject_uevent(&k->kobj, KOBJ_ADD)
->如果kobj的kset和parent字段都不存在,说明找不到所属kset,也就没有 uevent_ops,不能产生事件,返回错误信息;相反则找到了存在kset的kobj 或父kobject(依次往上找),并赋值给uevent_ops。
->add_uevent_var()kobj_uevent_env填充action_string,kobject路径, 子系统名称以及其他指定环境变量
->调用uevent_ops的uevent函数,编程人员可在此函数中实现自定义的 功能。
->设置KOBJ_ADD和KOBJ_REMOVE的标志。
->添加HOME和PATH环境变量。
->调用hotplug函数。
(2)kset_unregister() 减少其内嵌的kobj计数,为0则释放其内存空间。
常用函数:
1 #define MKDEV(major,minor) (((major) << MINORBITS) | (minor)) 将主设备号和次设备号转换成 dev_t类型
2 struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
相关的几个接口:
->LIST_HEAD()
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
常见函数:
cdev_alloc(void)
-> kzalloc(sizeof(struct cdev), GFP_KERNEL)
->INIT_LIST_HEAD(&p->list)
->kobject_init(&p->kobj, &ktype_cdev_dynamic)
cdev_init(...)
->INIT_LIST_HEAD(&cdev->list)
->kobject_init(&cdev->kobj, &ktype_cdev_default)
->cdev->ops = fops;
cdev_add(...)
->kobj_map(...) kobj_map 结构的 cdev_map 变量中包含一个散列表用来快速存取所有的对象。
kobj_map() 函数就是用来把字符设备编号和 cdev 结构变量一起保 存到 cdev_map 这个散列表里。当后续要打开一个字符设备文件时, 通过调用 kobj_lookup() 函数,根据设备编号就可以找到 cdev 结 构变量,从而取出其中的 ops 字段。
0 0
- Linux网络设备驱动结构
- linux mmc 驱动结构
- linux驱动结构
- Linux GPIO驱动结构
- linux设备驱动之UART驱动结构
- Linux设备驱动之UART驱动结构
- Linux设备驱动之UART驱动结构
- Linux设备驱动之UART驱动结构
- 升级Linux硬件驱动结构
- Linux网络设备驱动结构概述
- Linux字符驱动--结构分析
- linux驱动结构之device
- linux驱动结构之device_driver
- Linux字符设备驱动结构
- linux设备驱动结构梳理
- linux驱动结构之device
- linux驱动基本结构分析
- Linux网络设备驱动结构概述
- 大龄青年,啃语言
- swift 动画集合Animation
- Praat在CentOS 6.5中安装出现./praat /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.18' not found错误的解决办法
- 阅读android程序从AndroidManifest.xml开始
- Oracle启动监听遇到的问题
- linux驱动结构
- 将特殊字符插入数据库
- JVM学习笔记系列
- <leetcode系列> Linked List Cycle
- 图像分割之(二)Graph Cut(图割)
- [转载]java servlet过滤器控制frame框架中的页面跳转
- 微信分享SDK开发
- hihocoder 1103 Colorful Lecture Note(字符串处理)
- C语言中的值传递和引用传递(地址传递)