看SPI驱动核心模块时,看到用到很多klist,之前没多深入理解,现在来一步步分析源码。klist是对list_head的扩展,实现代码很少。内核代码:
include/linux/klist.h
lib/klist.c
----------------------
先要有一点点预备知识——list_head
----------------------
先看看头文件如何定义klist,以及一些基本操作方法接口。
----------------------
klist头文件 /* 头文件 */
1/*
2 * klist.h - Some generic list helpers, extending struct list_head a bit.
3 *
4 * Implementations are found in lib/klist.c
5 *
6 *
7 * Copyright (C) 2005 Patrick Mochel
8 *
9 * This file is rleased under the GPL v2.
10 */
11
12#ifndef _LINUX_KLIST_H
13#define _LINUX_KLIST_H
14
/* 自旋锁,这个过几天认真看下实现,具体作用就是多处理器的临界操作锁
* 对于嵌入式单处理器比较少用到
*/
15#include
/* 这个是内核引用次数的原子变量定义和原子操作
* 操作接口就是原子变量的增加get、减少put,以此实现内核对象引用次数操作
*/
16#include
/* 内核链表list_head */
17#include
18
/* 先声明klist_node节点,在后面定义 */
19struct klist_node;
/* klist结构体定义 */
20struct klist {
/* klist操作自旋锁 */
21 spinlock_t k_lock;
/* 内核链表 */
22 struct list_head k_list;
/* 获取klist_node节点方法 */
23 void (*get)(struct klist_node *);
/* 添加klist_node节点方法 */
24 void (*put)(struct klist_node *);
25} __attribute__ ((aligned (sizeof(void *))));/* 按指针大小对齐 */
26
/* 定义klist链表初始化宏
* 名字初始化锁、链表、get、put方法
*/
27#define KLIST_INIT(_name, _get, _put) \
/* 初始化为解锁状态 */
28 { .k_lock = __SPIN_LOCK_UNLOCKED(_name.k_lock), \
/* 初始化链表 */
29 .k_list = LIST_HEAD_INIT(_name.k_list), \
/* get方法 */
30 .get = _get, \
/* put方法 */
31 .put = _put, }
32
/* 定义并初始化链表 */
33#define DEFINE_KLIST(_name, _get, _put) \
34 struct klist _name = KLIST_INIT(_name, _get, _put)
35
/* klist初始化接口,在klist.c里具体分析 */
36extern void klist_init(struct klist *k, void (*get)(struct klist_node *),
37 void (*put)(struct klist_node *));
38
/* 节点结构体 */
39struct klist_node {
40 void *n_klist; /* never access directly */
/* 节点链表入口 */
41 struct list_head n_node;
/* 引用次数的一个原子变量 */
42 struct kref n_ref;
43};
44
/* 下面是链表操作方法声明,在klist.c具体分析 */
45extern void klist_add_tail(struct klist_node *n, struct klist *k);
46extern void klist_add_head(struct klist_node *n, struct klist *k);
47extern void klist_add_after(struct klist_node *n, struct klist_node *pos);
48extern void klist_add_before(struct klist_node *n, struct klist_node *pos);
49
50extern void klist_del(struct klist_node *n);
51extern void klist_remove(struct klist_node *n);
52
53extern int klist_node_attached(struct klist_node *n);
54
55
/* klist迭代器和操作方法,关于迭代器比较难理解,先看klist.c再说 */
56struct klist_iter {
57 struct klist *i_klist;
58 struct klist_node *i_cur;
59};
60
61
62extern void klist_iter_init(struct klist *k, struct klist_iter *i);
63extern void klist_iter_init_node(struct klist *k, struct klist_iter *i,
64 struct klist_node *n);
65