linux设备驱动模型一三基础结构之示例

前面我们了解了设备驱动模型的三个基本结构,以及它们的相关操作函数,这里我们以实例来看一下它们的用法。

首先定义一个内嵌的kobject结构:

struct test_container {int member;struct kobject kobj;};

定义了一个kobject和一个member成员,主要就是嵌套了kobject结构。

struct test_container *con1, *con2, *con3;struct kset *test_kset;struct kobj_type test_type;定义了三个test_container变量,一个kset,一个kobj_type.struct attribute name_attr = {.name = "name",.mode = 0666,};struct attribute val_attr = {.name = "member",.mode = 0666,};struct attribute *test_attrs[] = {&name_attr, &val_attr,NULL,};定义了两个属性变量,name和member,以及它们的访问权限,最后把它们都放到一个属性数组中。这里要注意的是属性数组中的最后一项为NULL.ssize_t test_show(struct kobject *kobj, struct attribute *attr, char *buffer){struct test_container *obj = container_of(kobj, struct test_container, kobj);ssize_t count = 0;if (strcmp(attr->name, "name") == 0) {count = sprintf(buffer, "%s\n", kobject_name(kobj));} else if (strcmp(attr->name, "member") == 0) {count = sprintf(buffer, "%d\n", obj->member);}return count;}ssize_t test_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size){struct test_container *obj = container_of(kobj, struct test_container, kobj);if (strcmp(attr->name, "member") == 0) {sscanf(buffer, "%d", &obj->member);}return size;}struct sysfs_ops test_sysfsops = {.show = test_show,.store = test_store,};定义文件读写函数,并赋值到sysfs_ops结构的变量test_sysfsops中。void obj_release(struct kobject *kobj){struct test_container *obj = container_of(kobj, struct test_container, kobj);printk(KERN_INFO "obj_release,name is: %s\n", kobject_name(&obj->kobj));kfree(obj);}当konject释放的时候调用。static int __init testkset_init(void){printk(KERN_WARNING "test_init\n");test_kset = kset_create_and_add("test_kset", NULL, NULL);if (!test_kset) {return -ENOMEM;}con1 = kzalloc(sizeof(struct test_container), GFP_KERNEL);if (!con1) {kset_unregister(test_kset);return -ENOMEM;}con1->member = 1;con2 = kzalloc(sizeof(struct test_container), GFP_KERNEL);if (!con2) {kset_unregister(test_kset);kfree(con1);return -ENOMEM;}con2->member = 2;con3 = kzalloc(sizeof(struct test_container), GFP_KERNEL);if (!con3) {kset_unregister(test_kset);kfree(con1);kfree(con2);return -ENOMEM;}con3->member = 3;con1->kobj.kset = test_kset;con2->kobj.kset = test_kset;con3->kobj.kset = test_kset;test_type.release = obj_release;test_type.default_attrs = test_attrs;test_type.sysfs_ops = &test_sysfsops;kobject_init_and_add(&con1->kobj, &test_type, NULL, "con1");kobject_init_and_add(&con2->kobj, &test_type, &con1->kobj, "con2");kobject_init_and_add(&con3->kobj, &test_type, NULL, "con3");return 0;}这里主要进行kset,kobject的初始化操作,对于kset,直接调用kset_create_and_add初始化并添加到体系结构中,而对于 kobject,首先是赋值,然后设置kset,最后调用kobject_init_and_add添加到体系结构。这里还对这个ktype进行了赋值,进行了属性的相关设置 。static void __exit testkset_exit(void){printk(KERN_INFO "test_kset_exit\n");kobject_del(&con1->kobj);kobject_put(&con1->kobj);kobject_del(&con2->kobj);kobject_put(&con2->kobj);kobject_del(&con3->kobj);kobject_put(&con3->kobj);kset_unregister(test_kset);return;}kobject_del的作用是把kobject从设备模型的那棵树里摘掉,同时sysfs里相应的目录也会删除。这里需要指出的是,释放的顺序应该是先子对象,后父对象。因为kobject_init_and_add和kobject_add这两个函数会调用kobject_get来增加父对象的引用计数,所以kobject_del需要调用kobject_put来减少父对象的引用计数。在本例中,如果先通过kobject_put来释放obj1,那kobject_del(&obj2->kobj)就会出现内存错误。

这个示例构建了一个如下的架构:

相关的/sys目录结构及属性操作:

root@leaves-desktop:/home/leaves/Test/ldm/ldm2# insmod ldm2.ko root@leaves-desktop:/home/leaves/Test/ldm/ldm2# ll /systotal 4drwxr-xr-x 13 root root 0 May 15 14:39 ./drwxr-xr-x 26 root root 4096 Mar 14 14:28 ../drwxr-xr-x 2 root root 0 May 15 14:39 block/drwxr-xr-x 22 root root 0 May 15 14:39 bus/drwxr-xr-x 45 root root 0 May 15 14:39 class/drwxr-xr-x 4 root root 0 May 15 14:39 dev/drwxr-xr-x 14 root root 0 May 15 14:39 devices/drwxr-xr-x 4 root root 0 May 15 14:39 firmware/drwxr-xr-x 6 root root 0 May 15 14:39 fs/drwxr-xr-x 7 root root 0 May 15 14:39 kernel/drwxr-xr-x 105 root root 0 May 15 14:39 module/drwxr-xr-x 2 root root 0 May 15 14:39 power/drwxr-xr-x 4 root root 0 May 15 14:43 test_kset/root@leaves-desktop:/home/leaves/Test/ldm/ldm2# ll /sys/test_kset/total 0drwxr-xr-x 4 root root 0 May 15 14:43 ./drwxr-xr-x 13 root root 0 May 15 14:39 ../drwxr-xr-x 3 root root 0 May 15 14:43 con1/drwxr-xr-x 2 root root 0 May 15 14:43 con3/root@leaves-desktop:/home/leaves/Test/ldm/ldm2# ll /sys/test_kset/concon1/ con3/ root@leaves-desktop:/home/leaves/Test/ldm/ldm2# ll /sys/test_kset/concon1/ con3/ root@leaves-desktop:/home/leaves/Test/ldm/ldm2# ll /sys/test_kset/con1/total 0drwxr-xr-x 3 root root 0 May 15 14:43 ./drwxr-xr-x 4 root root 0 May 15 14:43 ../drwxr-xr-x 2 root root 0 May 15 14:43 con2/-rw-rw-rw- 1 root root 4096 May 15 14:43 member-rw-rw-rw- 1 root root 4096 May 15 14:43 nameroot@leaves-desktop:/home/leaves/Test/ldm/ldm2# cat /sys/test_kset/con1/member 1root@leaves-desktop:/home/leaves/Test/ldm/ldm2# cat /sys/test_kset/con1/name con1root@leaves-desktop:/home/leaves/Test/ldm/ldm2# ll /sys/test_kset/con1/con2/ total 0drwxr-xr-x 2 root root 0 May 15 14:43 ./drwxr-xr-x 3 root root 0 May 15 14:43 ../-rw-rw-rw- 1 root root 4096 May 15 14:44 member-rw-rw-rw- 1 root root 4096 May 15 14:44 nameroot@leaves-desktop:/home/leaves/Test/ldm/ldm2# cat /sys/test_kset/concon1/ con3/ root@leaves-desktop:/home/leaves/Test/ldm/ldm2# cat /sys/test_kset/con1/con2/member 2root@leaves-desktop:/home/leaves/Test/ldm/ldm2# echo 4 /sys/test_kset/con1/member 4 /sys/test_kset/con1/memberroot@leaves-desktop:/home/leaves/Test/ldm/ldm2# cat /sys/test_kset/con1/member1root@leaves-desktop:/home/leaves/Test/ldm/ldm2# echo 4 > /sys/test_kset/con1/member root@leaves-desktop:/home/leaves/Test/ldm/ldm2# cat /sys/test_kset/con1/member4root@leaves-desktop:/home/leaves/Test/ldm/ldm2# rmmod ldm2.ko root@leaves-desktop:/home/leaves/Test/ldm/ldm2#

而不去欣赏今天就开在我们窗口的玫瑰。

linux设备驱动模型一三基础结构之示例

相关文章:

你感兴趣的文章:

标签云: