Linux内核链表listhead扩展klist.docx

上传人:b****6 文档编号:7087047 上传时间:2023-01-17 格式:DOCX 页数:27 大小:31.69KB
下载 相关 举报
Linux内核链表listhead扩展klist.docx_第1页
第1页 / 共27页
Linux内核链表listhead扩展klist.docx_第2页
第2页 / 共27页
Linux内核链表listhead扩展klist.docx_第3页
第3页 / 共27页
Linux内核链表listhead扩展klist.docx_第4页
第4页 / 共27页
Linux内核链表listhead扩展klist.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

Linux内核链表listhead扩展klist.docx

《Linux内核链表listhead扩展klist.docx》由会员分享,可在线阅读,更多相关《Linux内核链表listhead扩展klist.docx(27页珍藏版)》请在冰豆网上搜索。

Linux内核链表listhead扩展klist.docx

Linux内核链表listhead扩展klist

看SPI驱动核心模块时,看到用到很多klist,之前没多深入理解,现在来一步步分析源码。

klist是对list_head的扩展,实现代码很少。

内核代码:

include/linux/klist.h

lib/klist.c

----------------------

先要有一点点预备知识——list_head

----------------------

先看看头文件如何定义klist,以及一些基本操作方法接口。

----------------------

klist头文件/*头文件*/

1/*

2*klist.h-Somegenericlisthelpers,extendingstructlist_headabit.

3*

4*Implementationsarefoundinlib/klist.c

5*

6*

7*Copyright(C)2005PatrickMochel

8*

9*ThisfileisrleasedundertheGPLv2.

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节点,在后面定义*/

19structklist_node;

/*klist结构体定义*/

20structklist{

/*klist操作自旋锁*/

21spinlock_tk_lock;

/*内核链表*/

22structlist_headk_list;

/*获取klist_node节点方法*/

23void(*get)(structklist_node*);

/*添加klist_node节点方法*/

24void(*put)(structklist_node*);

25}__attribute__((aligned(sizeof(void*))));/*按指针大小对齐*/

26

/*定义klist链表初始化宏

*名字初始化锁、链表、get、put方法

*/

27#defineKLIST_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#defineDEFINE_KLIST(_name,_get,_put)\

34structklist_name=KLIST_INIT(_name,_get,_put)

35

/*klist初始化接口,在klist.c里具体分析*/

36externvoidklist_init(structklist*k,void(*get)(structklist_node*),

37void(*put)(structklist_node*));

38

/*节点结构体*/

39structklist_node{

40void*n_klist;/*neveraccessdirectly*/

/*节点链表入口*/

41structlist_headn_node;

/*引用次数的一个原子变量*/

42structkrefn_ref;

43};

44

/*下面是链表操作方法声明,在klist.c具体分析*/

45externvoidklist_add_tail(structklist_node*n,structklist*k);

46externvoidklist_add_head(structklist_node*n,structklist*k);

47externvoidklist_add_after(structklist_node*n,structklist_node*pos);

48externvoidklist_add_before(structklist_node*n,structklist_node*pos);

49

50externvoidklist_del(structklist_node*n);

51externvoidklist_remove(structklist_node*n);

52

53externintklist_node_attached(structklist_node*n);

54

55

/*klist迭代器和操作方法,关于迭代器比较难理解,先看klist.c再说*/

56structklist_iter{

57structklist*i_klist;

58structklist_node*i_cur;

59};

60

61

62externvoidklist_iter_init(structklist*k,structklist_iter*i);

63externvoidklist_iter_init_node(structklist*k,structklist_iter*i,

64structklist_node*n);

65externvoidklist_iter_exit(structklist_iter*i);

66externstructklist_node*klist_next(structklist_iter*i);

67

68#endif

69----------------------

klist实现代码1/*

2*klist.c-Routinesformanipulatingklists.

3*

4*Copyright(C)2005PatrickMochel

5*

6*ThisfileisreleasedundertheGPLv2.

7*

8*Thisklistinterfaceprovidesacoupleofstructuresthatwraparound

9*structlist_headtoprovideexplicitlist"head"(structklist)andlist

10*"node"(structklist_node)objects.Forstructklist,aspinlockis

11*includedthatprotectsaccesstotheactuallistitself.struct

12*klist_nodeprovidesapointertotheklistthatownsitandakref

13*referencecountthatindicatesthenumberofcurrentusersofthatnode

14*inthelist.

15*

16*Theentirepointistoprovideaninterfaceforiteratingoveralist

17*thatissafeandallowsformodificationofthelistduringthe

18*iteration(e.g.insertionandremoval),includingmodificationofthe

19*currentnodeonthelist.

20*

21*Itworksusinga3rdobjecttype-structklist_iter-thatisdeclared

22*andinitializedbeforeaniteration.klist_next()isusedtoacquirethe

23*nextelementinthelist.ItreturnsNULLiftherearenomoreitems.

24*Internally,thatroutinetakestheklist'slock,decrementsthe

25*referencecountofthepreviousklist_nodeandincrementsthecountof

26*thenextklist_node.Itthendropsthelockandreturns.

27*

28*Thereareprimitivesforaddingandremovingnodesto/fromaklist.

29*Whendeleting,klist_del()willsimplydecrementthereferencecount.

30*Onlywhenthecountgoesto0isthenoderemovedfromthelist.

31*klist_remove()willtrytodeletethenodefromthelistandblockuntil

32*itisactuallyremoved.Thisisusefulforobjects(likedevices)that

33*havebeenremovedfromthesystemandmustbefreed(butmustwaituntil

34*allaccessorshavefinished).

35*/

36

37#include

38#include

39#include

40

/*下面定义一些节点操作方法,先看下去,再来理解这些操作真正作用*/

41/*

42*Usethelowestbitofn_klisttomarkdeletednodesandexclude

43*deadonesfromiteration.

44*/

45#defineKNODE_DEAD1LU

46#defineKNODE_KLIST_MASK~KNODE_DEAD

47

/*由节点获取链表头*/

48staticstructklist*knode_klist(structklist_node*knode)

49{

50return(structklist*)

51((unsignedlong)knode->n_klist&KNODE_KLIST_MASK);

52}

53

/*判断节点“死了”*/

54staticboolknode_dead(structklist_node*knode)

55{

56return(unsignedlong)knode->n_klist&KNODE_DEAD;

57}

58

/*设置节点的链表*/

59staticvoidknode_set_klist(structklist_node*knode,structklist*klist)

60{

61knode->n_klist=klist;

62/*noknodedeservestostartitslifedead*/

/*没有节点刚开始就是“死的”*/

63WARN_ON(knode_dead(knode));

64}

65

/*“杀死”节点*/

66staticvoidknode_kill(structklist_node*knode)

67{

68/*andnoknodeshoulddietwiceevereither,seewe'reveryhumane*/

/*没有节点能“死”两次,瞧我们多人性化*/

69WARN_ON(knode_dead(knode));

70*(unsignedlong*)&knode->n_klist|=KNODE_DEAD;

71}

72

73/**

74*klist_init-Initializeakliststructure.

75*@k:

Theklistwe'reinitializing.

76*@get:

Thegetfunctionfortheembeddingobject(NULLifnone)

77*@put:

Theputfunctionfortheembeddingobject(NULLifnone)

78*

79*Initialisesthekliststructure.Iftheklist_nodestructuresare

80*goingtobeembeddedinrefcountedobjects(necessaryforsafe

81*deletion)thentheget/putargumentsareusedtoinitialise

82*functionsthattakeandreleasereferencesontheembedding

83*objects.

84*/

/*klist初始化接口

*get/put方法用来操作klist_node

*/

85voidklist_init(structklist*k,void(*get)(structklist_node*),

86void(*put)(structklist_node*))

87{

88INIT_LIST_HEAD(&k->k_list);

89spin_lock_init(&k->k_lock);

90k->get=get;

91k->put=put;

92}

93EXPORT_SYMBOL_GPL(klist_init);

94

/*将节点加入到链表头*/

95staticvoidadd_head(structklist*k,structklist_node*n)

96{

97spin_lock(&k->k_lock);

98list_add(&n->n_node,&k->k_list);

99spin_unlock(&k->k_lock);

100}

101

/*将节点加入到链表尾*/

102staticvoidadd_tail(structklist*k,structklist_node*n)

103{

104spin_lock(&k->k_lock);

105list_add_tail(&n->n_node,&k->k_list);

106spin_unlock(&k->k_lock);

107}

108

/*节点初始化

*包括初始化链表、引用计数、设置指向klist

*/

109staticvoidklist_node_init(structklist*k,structklist_node*n)

110{

111INIT_LIST_HEAD(&n->n_node);

112kref_init(&n->n_ref);

113knode_set_klist(n,k);

/*如果klist的get方法存在,则调用获取节点*/

114if(k->get)

115k->get(n);

116}

117

118/**

119*klist_add_head-Initializeaklist_nodeandaddittofront.

120*@n:

nodewe'readding.

121*@k:

klistit'sgoingon.

122*/

/*将节点n初始化并加入到klist的头*/

123voidklist_add_head(structklist_node*n,structklist*k)

124{

125klist_node_init(k,n);

126add_head(k,n);

127}

128EXPORT_SYMBOL_GPL(klist_add_head);

129

130/**

131*klist_add_tail-Initializeaklist_nodeandaddittoback.

132*@n:

nodewe'readding.

133*@k:

klistit'sgoingon.

134*/

/*将节点n初始化并加入到klist的尾*/

135voidklist_add_tail(structklist_node*n,structklist*k)

136{

137klist_node_init(k,n);

138add_tail(k,n);

139}

140EXPORT_SYMBOL_GPL(klist_add_tail);

141

142/**

143*klist_add_after-Initaklist_nodeandadditafteranexistingnode

144*@n:

nodewe'readding.

145*@pos:

nodetoput@nafter

146*/

/*在节点pos后面插入节点n*/

147voidklist_add_after(structklist_node*n,structklist_node*pos)

148{

149structklist*k=knode_klist(pos);

150

151klist_node_init(k,n);

152spin_lock(&k->k_lock);

153list_add(&n->n_node,&pos->n_node);

154spin_unlock(&k->k_lock);

155}

156EXPORT_SYMBOL_GPL(klist_add_after);

157

158/**

159*klist_add_before-Initaklist_nodeandadditbeforeanexistingnode

160*@n:

nodewe'readding.

161*@pos:

nodetoput@nafter

162*/

/*在节点pos前面插入节点n*/

163voidklist_add_before(structklist_node*n,structklist_node*pos)

164{

165structklist*k=knode_klist(pos);

166

167klist_node_init(k,n);

168spin_lock(&k->k_lock);

169list_add_tail(&n->n_node,&pos->n_node);

170spin_unlock(&k->k_lock);

171}

172EXPORT_SYMBOL_GPL(klist_add_before);

173

/*等待者结构体,用于删除节点,删除完成唤醒进程*/

174structklist_waiter{

175structlist_headlist;

176structklist_node*node;

177structtask_struct*process;

178intwoken;

179};

180

/*定义并初始化klist节点移除自旋锁*/

181staticDEFINE_SPINLOCK(klist_remove_lock);

/*定义一个等待器的链表*/

182staticLIST_HEAD(klist_remove_waiters);

183

184staticvoidklist_release(structkref*kref)

185{

186structklist_waiter*waiter,*tmp;

187structklist_node*n=container_of(kref,structklist_node,n_ref);

188

189WARN_ON(!

knode_dead(n));

/*删除链表中的节点入口*/

190list_del(&n->n_node);

191spin_lock(&klist_remove_lock);

/*内核链表操作宏include/linux/list.h,遍历klist节点移除等待链表*/

192list_for_each

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1