LDD3的第14章《Linux设备模型》一章节把Linux内核中的很多结构体串讲了一遍,满满的干货,非常值得一看,这里简单的笔记下代码注释吧。作者的语文实在太差,很多阅读心得不知道怎么笔记出来,还请各位高手勿喷~
Linux内核和驱动开发时,由于各种结构体变量见相互引用,因此,当回收内存时,由于引用没有清理,很容易发生内存指向错误。因此,Linux使用引用计数方式来代替简单的malloc,free。不过由于Linux的内核是以C为开发语言,不是C++,无法使用继承和派生,因此只能使用结构体互相包含和containerof方式来使用引用计数框架,读起来还是比较晦涩的。
CONTENTS
\linux-2.6.11\include\linux\kref.h
/* 引用计数的实现结构体 */ #ifndef _KREF_H_ #define _KREF_H_ #ifdef __KERNEL__ #include <linux/types.h> #include <asm/atomic.h> /* 引用计数的原理很简单,使用时加1,不用时减1,如果减为0 则调用释放函数。 */ struct kref { /* Linux 使用原子变量来计数,这样可以防止多CPU,多进程时的竞态现象发生 */ atomic_t refcount; }; void kref_init(struct kref *kref);/* 初始化一个引用计数结构体 */ void kref_get(struct kref *kref);/* 增加一个引用计数 */ void kref_put(struct kref *kref, void (*release) (struct kref *kref));/* 减少一个引用计数 */ #endif /* __KERNEL__ */ #endif /* _KREF_H_ */
\linux-2.6.11\lib\kref.c
#include <linux/kref.h> #include <linux/module.h> /** * kref_init - initialize object. * @kref: object in question. */ /* 初始化一个引用计数,这里可以看到引用计数初始化为1 */ void kref_init(struct kref *kref) { atomic_set(&kref->refcount,1); } /** * kref_get - increment refcount for object. * @kref: object. */ /* 增加一个引用计数,可以发现这里是原子操作 */ void kref_get(struct kref *kref) { WARN_ON(!atomic_read(&kref->refcount)); atomic_inc(&kref->refcount); } /** * kref_put - decrement refcount for object. * @kref: object. * @release: pointer to the function that will clean up the object when the * last reference to the object is released. * This pointer is required, and it is not acceptable to pass kfree * in as this function. * * Decrement the refcount, and if 0, call release(). */ ;/* 减少一个引用计数 */ void kref_put(struct kref *kref, void (*release) (struct kref *kref)) { WARN_ON(release == NULL); WARN_ON(release == (void (*)(struct kref *))kfree); if (atomic_dec_and_test(&kref->refcount)) release(kref);/* 如果引用计数为0,就调用释放函数 */ }
发表评论