1.. include:: ../disclaimer-zh_CN.rst
2
3:Original: Documentation/core-api/kref.rst
4
5������:
6
7��������� Yanteng Si <siyanteng@loongson.cn>
8
9���������
10
11 <���������������������������������������������������������������������>
12
13.. _cn_core_api_kref.rst:
14
15=================================
16���������������������������������������krefs���
17=================================
18
19:������: Corey Minyard <minyard@acm.org>
20:������: Thomas Hellstrom <thellstrom@vmware.com>
21
22���������������������������Greg Kroah-Hartman2004���������krefs���OLS���������������������
23������������������������������������:
24
25  - http://www.kroah.com/linux/talks/ols_2004_kref_paper/Reprint-Kroah-Hartman-OLS2004.pdf
26  - http://www.kroah.com/linux/talks/ols_2004_kref_talk/
27
28������
29====
30
31krefs������������������������������������������������������������������������������������������������������
32������������refcounts���������������������������������������������������������������������krefs������
33������������
34
35���������kref������������������������������������������������::
36
37    struct my_data
38    {
39	.
40	.
41	struct kref refcount;
42	.
43	.
44    };
45
46kref���������������������������������������������������
47
48���������
49======
50
51������������������kref��������������������� ���������������������������������������kref_init::
52
53     struct my_data *data;
54
55     data = kmalloc(sizeof(*data), GFP_KERNEL);
56     if (!data)
57            return -ENOMEM;
58     kref_init(&data->refcount);
59
60������kref������refcount���������1���
61
62Kref������
63========
64
65������������������������������kref������������������������������:
66
671) ������������������������������������������������������������������������������������������������������������
68   ���������������������������������������kref_get()������refcount::
69
70       kref_get(&data->refcount);
71
72	���������������������������������kref-ed���������������������������refcount���������������������
73	������������������������������������������
74
752) ���������������������������������������������������������kref_put()::
76
77       kref_put(&data->refcount, data_release);
78
79   ������������������������������������������������������������������������������������������������������������
80   ���������������������������������������������������������kref-ed���������������������������������������
81   ������������������������������������������
82
833) ���������������������������������kref-ed���������������������������������������������������������������
84   ������������������������kref_put()������������������kref_get()������������������������kref_get()
85   ���������������������������
86
87���������������������������������������������������������������������������������������::
88
89    void data_release(struct kref *ref)
90    {
91	struct my_data *data = container_of(ref, struct my_data, refcount);
92	kfree(data);
93    }
94
95    void more_data_handling(void *cb_data)
96    {
97	struct my_data *data = cb_data;
98	.
99	. do stuff with data here
100	.
101	kref_put(&data->refcount, data_release);
102    }
103
104    int my_data_handler(void)
105    {
106	int rv = 0;
107	struct my_data *data;
108	struct task_struct *task;
109	data = kmalloc(sizeof(*data), GFP_KERNEL);
110	if (!data)
111		return -ENOMEM;
112	kref_init(&data->refcount);
113
114	kref_get(&data->refcount);
115	task = kthread_run(more_data_handling, data, "more_data_handling");
116	if (task == ERR_PTR(-ENOMEM)) {
117		rv = -ENOMEM;
118	        kref_put(&data->refcount, data_release);
119		goto out;
120	}
121
122	.
123	. do stuff with data here
124	.
125    out:
126	kref_put(&data->refcount, data_release);
127	return rv;
128    }
129
130���������������������������������������������������������kref_put()���������������������������������������
131���������kref_get()���������������������������������������������������������������������������������
132refcount���put���������������������������������������������������������������������������������������������
133
134������������������������kref_put()������������������������������������������2���������������������������
135������������������kref_init()���kref_get()���������2������
136
137������������������1������ "before "���������������������������������������������::
138
139	task = kthread_run(more_data_handling, data, "more_data_handling");
140	if (task == ERR_PTR(-ENOMEM)) {
141		rv = -ENOMEM;
142		goto out;
143	} else
144		/* BAD BAD BAD - ������������������ */
145		kref_get(&data->refcount);
146
147���������������������������������������������������������������������������������������������������������������
148���������������������������������������������������������������������������������������������������������������
149���������������������������������������������������������������������������������������������������������������
150������������������
151
152������������������������������������get���put���������������������������������������������������������������
153���������������������������������������������������������������������������������������get���������������������
154put::
155
156	/* ���������������������(get)���������(put) */
157	kref_get(&obj->ref);
158	enqueue(obj);
159	kref_put(&obj->ref, obj_cleanup);
160
161���������enqueue��������������� ������������������������������������������::
162
163	enqueue(obj);
164	/* ������������������������obj������������������������������������refcount������������������
165	 ������������������������obj���! */
166
167���������������������������3���������������������������������������������������������������������krefed������������
168���������������������������������������������������������������������������������������������kref_get()������
169������������������3������������������������������������������������������������������������mutex���������������������
170���������::
171
172	static DEFINE_MUTEX(mutex);
173	static LIST_HEAD(q);
174	struct my_data
175	{
176		struct kref      refcount;
177		struct list_head link;
178	};
179
180	static struct my_data *get_entry()
181	{
182		struct my_data *entry = NULL;
183		mutex_lock(&mutex);
184		if (!list_empty(&q)) {
185			entry = container_of(q.next, struct my_data, link);
186			kref_get(&entry->refcount);
187		}
188		mutex_unlock(&mutex);
189		return entry;
190	}
191
192	static void release_entry(struct kref *ref)
193	{
194		struct my_data *entry = container_of(ref, struct my_data, refcount);
195
196		list_del(&entry->link);
197		kfree(entry);
198	}
199
200	static void put_entry(struct my_data *entry)
201	{
202		mutex_lock(&mutex);
203		kref_put(&entry->refcount, release_entry);
204		mutex_unlock(&mutex);
205	}
206
207���������������������������������������������������������kref_put()���������������������������������������������
208������������������������������������������������kfree()������������������������������������������������������kref_put()���
209������������::
210
211	static void release_entry(struct kref *ref)
212	{
213		/* ���������������������������kref_put()���������������������*/
214	}
215
216	static void put_entry(struct my_data *entry)
217	{
218		mutex_lock(&mutex);
219		if (kref_put(&entry->refcount, release_entry)) {
220			list_del(&entry->link);
221			mutex_unlock(&mutex);
222			kfree(entry);
223		} else
224			mutex_unlock(&mutex);
225	}
226
227������������������������������������������������������������������������������������������������������������������������
228������������������������������������������������������������������������������������������������������������������������
229������������������������
230
231���������������������������kref_get_unless_zero()������������������������::
232
233	static struct my_data *get_entry()
234	{
235		struct my_data *entry = NULL;
236		mutex_lock(&mutex);
237		if (!list_empty(&q)) {
238			entry = container_of(q.next, struct my_data, link);
239			if (!kref_get_unless_zero(&entry->refcount))
240				entry = NULL;
241		}
242		mutex_unlock(&mutex);
243		return entry;
244	}
245
246	static void release_entry(struct kref *ref)
247	{
248		struct my_data *entry = container_of(ref, struct my_data, refcount);
249
250		mutex_lock(&mutex);
251		list_del(&entry->link);
252		mutex_unlock(&mutex);
253		kfree(entry);
254	}
255
256	static void put_entry(struct my_data *entry)
257	{
258		kref_put(&entry->refcount, release_entry);
259	}
260
261������������put_entry()���������kref_put()���������mutex���������������������������������������
262kref_get_unless_zero������������������������������������������������������kref_get_unless_zero
263���������������������������������������������������������������������������������������kref_get_unless_zero
264���������������������������������������������������������������������kref_get_unless_zero()���������true���
265������������kref_get()���������
266
267Krefs���RCU
268==========
269
270������kref_get_unless_zero���������������������������������rcu���������������������������::
271
272	struct my_data
273	{
274		struct rcu_head rhead;
275		.
276		struct kref refcount;
277		.
278		.
279	};
280
281	static struct my_data *get_entry_rcu()
282	{
283		struct my_data *entry = NULL;
284		rcu_read_lock();
285		if (!list_empty(&q)) {
286			entry = container_of(q.next, struct my_data, link);
287			if (!kref_get_unless_zero(&entry->refcount))
288				entry = NULL;
289		}
290		rcu_read_unlock();
291		return entry;
292	}
293
294	static void release_entry_rcu(struct kref *ref)
295	{
296		struct my_data *entry = container_of(ref, struct my_data, refcount);
297
298		mutex_lock(&mutex);
299		list_del_rcu(&entry->link);
300		mutex_unlock(&mutex);
301		kfree_rcu(entry, rhead);
302	}
303
304	static void put_entry(struct my_data *entry)
305	{
306		kref_put(&entry->refcount, release_entry_rcu);
307	}
308
309������������������������������release_entry_rcu������������kref������������������������������������������rcu
310������������������������������������������kfree_rcu(entry, rhead)���������������������������kfree������
311������synchronize_rcu()������������synchronize_rcu()������������������������������������
312