好记性不如铅笔头

kernel, linux, 操作系统

Linux内核引用计数kref的简单笔记

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,就调用释放函数 */
}

 

发表评论

18 − 8 =

此站点使用 Akismet 来减少垃圾评论。了解我们如何处理您的评论数据