linux内核之klist链表

klist接口提供了两个封装了list_head的结构体,链表头klist和链表节点klist_node
对于结构体klist包含一个spinlock来提供访问保护.klist_node包含一个klist指针指向
归属的klist和kref引用计数器指示该节点的引用次数.
链表头结构体定义如下:

struct klist {
	spinlock_t		k_lock; // 自旋锁,用于保护列表的访问
	struct list_head	k_list; // 双向列表
	void			(*get)(struct klist_node *);//两个函数指针,是用来操作链表中的节点接口
	void			(*put)(struct klist_node *);//两个函数指针,是用来操作链表中的节点接口
} __attribute__ ((aligned (sizeof(void *))));

链表节点结构体定义如下:

struct klist_node {
	void			*n_klist;	/* never access directly */ //是一个空指针,随便用来指啥,但在我们的klist原语中是用来指向链表头的。另外其最低位用来做标志位
	struct list_head	n_node; //双向链表,用来联系各节点及链表头
	struct kref		n_ref;//引用计数,是个int型计数器
};

这两个结构体单独使用没什么意义,一般都是嵌入到更大的结构体来组成链表.在这里举例来说明.
1.subsys_private结构体用于bustype/class结构体来为驱动内核保存私有数据 (structure to hold the private to the driver core portions of the bus_type/class structure),其中struct klist klist_devices,struct klist klist_drivers成员就是两个klist内嵌链表

struct subsys_private {
	struct kset subsys; // the struct kset that defines this subsystem
	struct kset *devices_kset; // the list of devices associated

	struct kset *drivers_kset; // the list of drivers associated
	struct klist klist_devices;// the klist to iterate over the @devices_kset
	struct klist klist_drivers;// the klist to iterate over the @drivers_kset
.......
};

2.device 结构体内嵌链表节点

struct device {
	........
	struct klist_node	knode_class;
	.........
};

3.内嵌链表头的初始化:

static void klist_class_dev_get(struct klist_node *n)
{
	struct device *dev = container_of(n, struct device, knode_class);

	get_device(dev);
}

static void klist_class_dev_put(struct klist_node *n)
{
	struct device *dev = container_of(n, struct device, knode_class);

	put_device(dev);
}

int __class_register(struct class *cls, struct lock_class_key *key)
{
	struct subsys_private *cp;
	.........
	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
	.........
}

4.内嵌链表添加节点

int device_add(struct device *dev)
{
........
	if (dev->class) {
		mutex_lock(&dev->class->p->class_mutex);
		/* tie the class to the device */
		klist_add_tail(&dev->knode_class,
			       &dev->class->p->klist_devices);
.........
}

猜你喜欢

转载自blog.csdn.net/qq_36412526/article/details/84302126
今日推荐