????Linux??????kref.txt???????????????????????kref??????????
???????????
????If you make a non-temporary copy of a pointer?? especially if it can be passed to another thread of execution?? you must increment the refcount with kref_get() before passing it off??
???????????
????When you are done with a pointer?? you must call kref_put()??
????????????
????If the code attempts to gain a reference to a kref-ed structure without already holding a valid pointer?? it must serialize access where a kref_put() cannot occur during the kref_get()?? and the structure must remain valid during the kref_get().
???????????????????????????????·????????????????????????????????????????·?????????????????????????????????kref_get?????????????????
????kref_init(&obj->ref);
????// do something here
????// ...
????kref_get(&obj->ref);
????call_something(obj);
????kref_put(&obj->ref);
????// do something here
????// ...
????kref_put(&obj->ref);
??????????????call_something???????kref_get??kref_put????????obj???????????????????????????????б?????
????????????????????·?????????????????????????????????????????????????????????????
????struct my_data
????{
????.
????.
????struct kref refcount;
????.
????.
????};
????void data_release(struct kref *ref)
????{
????struct my_data *data = container_of(ref?? struct my_data?? refcount);
????kfree(data);
????}
????void more_data_handling(void *cb_data)
????{
????struct my_data *data = cb_data;
????.
????. do stuff with data here
????.
????kref_put(&data->refcount?? data_release);
????}
????int my_data_handler(void)
????{
????int rv = 0;
????struct my_data *data;
????struct task_struct *task;
????data = kmalloc(sizeof(*data)?? GFP_KERNEL);
????if (!data)
????return -ENOMEM;
????kref_init(&data->refcount);
????kref_get(&data->refcount);
????task = kthread_run(more_data_handling?? data?? "more_data_handling");
????if (task == ERR_PTR(-ENOMEM)) {
????rv = -ENOMEM;
????goto out;
????}
????.
????. do stuff with data here
????.
????out:
????kref_put(&data->refcount?? data_release);
????return rv;
????}
????????????????????more_data_handling????????????????kref_get????????????????
?????????????????????“before”??kref_get???????????????????У???????????????kthread_run??????kref_get????????????????
????????????????????????????????kref_get????????????kref_put??
?????????????????????????????????????????????????????????????????????????????????????ü????????????????β???????????????????y????????????????kref_get??????y??????ü?????????????????????????????????????????????????л??????????????????mutex????????????????????
????static DEFINE_MUTEX(mutex);
????static LIST_HEAD(q);
????struct my_data
????{
????struct kref refcount;
????struct list_head link;
????};
????static struct my_data *get_entry()
????{
????struct my_data *entry = NULL;
????mutex_lock(&mutex);
????if (!list_empty(&q)) {
????entry = container_of(q.next?? struct my_q_entry?? link);
????kref_get(&entry->refcount);
????}
????mutex_unlock(&mutex);
????return entry;
????}
????static void release_entry(struct kref *ref)
????{
????struct my_data *entry = container_of(ref?? struct my_data?? refcount);
????list_del(&entry->link);
????kfree(entry);
????}
????static void put_entry(struct my_data *entry)
????{
????mutex_lock(&mutex);
????kref_put(&entry->refcount?? release_entry);
????mutex_unlock(&mutex);
????}
??????????????????mutex?????б???????????????mutex????????????????????????????????????????????????????A????container_of???entry??????????kref_get?????????B??????У??????B????????????kref_put????????????A????????????????????????????????????????????????л??????
?????????????kref??????????????????????????????Ч??????????