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