linux核心之klist連結串列
阿新 • • 發佈:2018-11-28
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);
.........
}