舟山網(wǎng)站開發(fā)網(wǎng)絡(luò)營銷和網(wǎng)上銷售的區(qū)別
文章目錄
- 1. 設(shè)備管理模型
- 2. 基本數(shù)據(jù)結(jié)構(gòu)
- 2.1 kobject
- 2.2 kset
1. 設(shè)備管理模型
設(shè)備模型是內(nèi)核提供的一個編寫驅(qū)動的架構(gòu)。
設(shè)備管理是設(shè)備-總線-驅(qū)動結(jié)構(gòu)。
linux中的設(shè)備是由樹狀模型組織的,從sysfs中可以查看樹狀結(jié)構(gòu)。
他本身實現(xiàn)了:
- 電源管理
- 熱插拔(hotplug)事件管理
2. 基本數(shù)據(jù)結(jié)構(gòu)
- kobject, kset, uevent
- device, device_driver, bus, class
2.1 kobject
許多內(nèi)核對象都是由kobject作為基類派生的。相同類型的kobject通過其內(nèi)嵌的list_head鏈成一個鏈表,然后使用另外一個結(jié)構(gòu)體kset(kobject的子類)來指向和管理這個列表。
struct kobject {const char *name;struct list_head entry;struct kobject *parent;struct kset *kset; /* 給相關(guān)的kobject分組,是kobj的集合 */struct kobj_type *ktype; /* 抽象出了一些kobj和sysfs的通用接口,描述kobj的行為 */struct kernfs_node *sd; /* sysfs 的文件節(jié)點 */struct kref kref; /* kobject的引用計數(shù) */
#ifdef CONFIG_DEBUG_KOBJECT_RELEASEstruct delayed_work release;
#endifunsigned int state_initialized:1;unsigned int state_in_sysfs:1;unsigned int state_add_uevent_sent:1;unsigned int state_remove_uevent_sent:1;unsigned int uevent_suppress:1;
};
一個新的kobject要加入到設(shè)備管理模型中,需要使用函數(shù):
/* 創(chuàng)建新的kobj */
struct kobject * __must_check kobject_create_and_add(const char *name,struct kobject *parent);
/* parent : 在sysfs中的父目錄,如果為NULL則表示在"/sys/"目錄下 *//* 添加已存在的的kobj */
int kobject_init_and_add(struct kobject *kobj,struct kobj_type *ktype, struct kobject *parent, const char *fmt, ...);
/* fmt一般是name, 也是sysfs中kobject對應(yīng)的目錄名 */
調(diào)用之前需要給kobj分配內(nèi)存,并初始化ktype,用于這個kset中kobject的通用操作,其中ktype如下:
struct kobj_type {void (*release)(struct kobject *kobj); /* 必須 */const struct sysfs_ops *sysfs_ops; /* 內(nèi)含show和store接口 */struct attribute **default_attrs; /* 每個屬性都在sysfs中有對應(yīng)的屬性文件 */const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);const void *(*namespace)(struct kobject *kobj);
};
2.2 kset
kset用于:
- 作為一組kobject的容器
- 是一個sysfs中的目錄,里面包含kset關(guān)聯(lián)的kobject
- kset可支持kobject的“熱插拔”,并影響uevent事件像用戶空間的報告方式
/*** struct kset - 一個子系統(tǒng)中,一系列kobject的集合** A kset defines a group of kobjects. They can be individually* different "types" but overall these kobjects all want to be grouped* together and operated on in the same manner. ksets are used to* define the attribute callbacks and other common events that happen to* a kobject.** @list: the list of all kobjects for this kset* @list_lock: a lock for iterating over the kobjects* @kobj: the embedded kobject for this kset (recursion, isn't it fun...)* @uevent_ops: the set of uevent operations for this kset. These are* called whenever a kobject has something happen to it so that the kset* can add new environment variables, or filter out the uevents if so* desired.*/
struct kset {struct list_head list;spinlock_t list_lock;struct kobject kobj;const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;
一個組織多個kobject的kset例程(節(jié)選):linux/samples/kobject/kset-example.c
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>MODULE_LICENSE("GPL");struct foo_obj {struct kobject kobj;int foo;int baz;int bar;
};
/* 從類型為kobj的結(jié)構(gòu)體成員的指針x,獲取該foo_obj類型結(jié)構(gòu)體的指針 */
#define to_foo_obj(x) container_of(x, struct foo_obj, kobj)static void foo_release(struct kobject *kobj)
{struct foo_obj *foo;foo = to_foo_obj(kobj);kfree(foo);
}/* 可以定義所屬kset的kobject的一些行為到default_attrs和sysfs_ops屬性中,現(xiàn)在僅* 使用release */
static struct kobj_type foo_ktype = {// .sysfs_ops = &foo_sysfs_ops,.release = foo_release,// .default_attrs = foo_default_attrs,
};static struct kset *example_kset;
static struct foo_obj *foo_obj;
static struct foo_obj *bar_obj;
static struct foo_obj *baz_obj;
/* 創(chuàng)建kset下的kobject */
static struct foo_obj *create_foo_obj(const char *name)
{struct foo_obj *foo;int retval;/* allocate the memory for the whole object */foo = kzalloc(sizeof(*foo), GFP_KERNEL);if (!foo)return NULL;/* 初始化kobject之前先確定所屬kset */foo->kobj.kset = example_kset;/* 初始化kobject添加到kernel中,并關(guān)聯(lián)ktype,會在sysfs中創(chuàng)建名為name的kobject文件夾* 第三個參數(shù)是父kobj,由于已確定kset,寫為NULL */retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);if (retval) {kobject_put(&foo->kobj);return NULL;}/* 通知用戶空間有一個新的內(nèi)核對象(kobject)已經(jīng)被添加到 sysfs 中。* 這對于用戶空間的監(jiān)控和管理工具來說是很有用的 */kobject_uevent(&foo->kobj, KOBJ_ADD);return foo;
}static void destroy_foo_obj(struct foo_obj *foo)
{kobject_put(&foo->kobj);
}static int __init example_init(void)
{/* 創(chuàng)建一個名為 "kset_example" 的kset, 路徑在/sys/kernel/ */example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);if (!example_kset)return -ENOMEM;/* 在已定義的kset下新增kobject */foo_obj = create_foo_obj("foo");if (!foo_obj)goto foo_error;bar_obj = create_foo_obj("bar");if (!bar_obj)goto bar_error;baz_obj = create_foo_obj("baz");if (!baz_obj)goto baz_error;return 0;baz_error:destroy_foo_obj(bar_obj);
bar_error:destroy_foo_obj(foo_obj);
foo_error:kset_unregister(example_kset);return -EINVAL;
}static void __exit example_exit(void)
{destroy_foo_obj(baz_obj);destroy_foo_obj(bar_obj);destroy_foo_obj(foo_obj);kset_unregister(example_kset);
}MODULE_AUTHOR("LUKEKE"); // 作者
MODULE_DESCRIPTION("kset test"); // 描述
MODULE_ALIAS("kset Learn"); // 別名module_init(example_init);
module_exit(example_exit);
運行結(jié)果:
[root@qemu_imx6ul:/sys/kernel]# ls
config irq rcu_expedited slab
debug mm rcu_normal uevent_helper
fscaps notes security uevent_seqnum
[root@qemu_imx6ul:/sys/kernel]# insmod ~/hello.ko
[root@qemu_imx6ul:/sys/kernel]# ls
config irq notes security uevent_seqnum
debug kset_example rcu_expedited slab
fscaps mm rcu_normal uevent_helper
[root@qemu_imx6ul:/sys/kernel]# cd kset_example/
[root@qemu_imx6ul:/sys/kernel/kset_example]# ls
bar baz foo
[root@qemu_imx6ul:/sys/kernel/kset_example]# ls bar/
[root@qemu_imx6ul:/sys/kernel/kset_example]# ls foo
下一篇文:sysfs