国产欧美一区二区精品行性色_91精品午夜在线观看_亚洲精品无码激情国产_91精品啪在线观看国产城中村_91看片国产一区二区色欲

始創(chuàng)于2000年 股票代碼:831685
咨詢熱線:0371-60135900 注冊有禮 登錄
  • 掛牌上市企業(yè)
  • 60秒人工響應(yīng)
  • 99.99%連通率
  • 7*24h人工
  • 故障100倍補償
全部產(chǎn)品
您的位置: 網(wǎng)站首頁 > 幫助中心>文章內(nèi)容

Linux內(nèi)核里的智能指針

發(fā)布時間:  2012/8/9 16:12:16
 在Linux內(nèi)核里,引用計數(shù)是通過struct kref結(jié)構(gòu)來實現(xiàn)的。在介紹如何使用kref之前,我們先來假設(shè)一個情景。假如您開發(fā)的是一個字符設(shè)備驅(qū)動,當(dāng)設(shè)備插上時,系統(tǒng)自動建立一個設(shè)備節(jié)點,用戶通過文件操作來訪問設(shè)備節(jié)點。

如上圖所示,最左邊的綠色框圖表示實際設(shè)備的插拔動作,中間黃色的框圖表示內(nèi)核中設(shè)備對象的生存周期,右邊藍(lán)色的框圖表示用戶程序系統(tǒng)調(diào)用的順序。如果用戶程序正在訪問的時候設(shè)備突然被拔掉,驅(qū)動程序里的設(shè)備對象是否立刻釋放呢?如果立刻釋放,用戶程序執(zhí)行的系統(tǒng)調(diào)用一定會發(fā)生內(nèi)存非法訪問;如果要等到用戶程序close之后再釋放設(shè)備對象,我們應(yīng)該怎么來實現(xiàn)?kref就是為了解決類似的問題而生的。

kref的定義非常簡單,其結(jié)構(gòu)體里只有一個原子變量。

struct kref {
	atomic_t refcount;
};

Linux內(nèi)核定義了下面三個函數(shù)接口來使用kref:

void kref_init(struct kref *kref);
void kref_get(struct kref *kref);
int kref_put(struct kref *kref, void (*release) (struct kref *kref));

我們先通過一段偽代碼來了解一下如何使用kref。

 

struct my_obj
{
	int val;
	struct kref refcnt;
};

struct my_obj *obj;

void obj_release(struct kref *ref) 
{
	struct my_obj *obj = container_of(ref, struct my_obj, refcnt);
	kfree(obj);
}

device_probe() 
{
	obj = kmalloc(sizeof(*obj), GFP_KERNEL);
	kref_init(&obj->refcnt);
}

device_disconnect() 
{
	kref_put(&obj->refcnt, obj_release);
}

.open() 
{
	kref_get(&obj->refcnt);
}

.close() 
{
	kref_put(&obj->refcnt, obj_release);
}

 

在這段代碼里,我們定義了obj_release來作為釋放設(shè)備對象的函數(shù),當(dāng)引用計數(shù)為0時,這個函數(shù)會被立刻調(diào)用來執(zhí)行真正的釋放動作。我們先在device_probe里把引用計數(shù)初始化為1,當(dāng)用戶程序調(diào)用open時,引用計數(shù)又會被加1,之后如果設(shè)備被拔掉,device_disconnect會減掉一個計數(shù),但此時refcnt還不是0,設(shè)備對象obj并不會被釋放,只有當(dāng)close被調(diào)用之后,obj_release才會執(zhí)行。

看完偽代碼之后,我們再來實戰(zhàn)一下。為了節(jié)省篇幅,這個實作并沒有建立一個字符設(shè)備,只是通過模塊的加載和卸載過程來對感受一下kref。

#include <linux/kernel.h>
#include <linux/module.h>

struct my_obj {
        int val;
        struct kref refcnt;
};

struct my_obj *obj;

void obj_release(struct kref *ref)
{
        struct my_obj *obj = container_of(ref, struct my_obj, refcnt);
        printk(KERN_INFO "obj_release\n");
        kfree(obj);
}

static int __init kreftest_init(void)
{
        printk(KERN_INFO "kreftest_init\n");
        obj = kmalloc(sizeof(*obj), GFP_KERNEL);
        kref_init(&obj->refcnt);
        return 0;
}

static void __exit kreftest_exit(void)
{
        printk(KERN_INFO "kreftest_exit\n");
        kref_put(&obj->refcnt, obj_release);
        return;
}

module_init(kreftest_init);
module_exit(kreftest_exit);

MODULE_LICENSE("GPL");

通過kbuild編譯之后我們得到kref_test.ko,然后我們順序執(zhí)行以下命令來掛載和卸載模塊。

sudo insmod ./kref_test.ko

sudo rmmod kref_test

此時,系統(tǒng)日志會打印出如下消息:

kreftest_init

kreftest_exit

obj_release

這正是我們預(yù)期的結(jié)果。

 

有了kref引用計數(shù),即使內(nèi)核驅(qū)動寫的再復(fù)雜,我們對內(nèi)存管理也應(yīng)該有信心了吧。


本文出自:億恩科技【www.cmtents.com】

服務(wù)器租用/服務(wù)器托管中國五強!虛擬主機域名注冊頂級提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM]

  • 您可能在找
  • 億恩北京公司:
  • 經(jīng)營性ICP/ISP證:京B2-20150015
  • 億恩鄭州公司:
  • 經(jīng)營性ICP/ISP/IDC證:豫B1.B2-20060070
  • 億恩南昌公司:
  • 經(jīng)營性ICP/ISP證:贛B2-20080012
  • 服務(wù)器/云主機 24小時售后服務(wù)電話:0371-60135900
  • 虛擬主機/智能建站 24小時售后服務(wù)電話:0371-60135900
  • 專注服務(wù)器托管17年
    掃掃關(guān)注-微信公眾號
    0371-60135900
    Copyright© 1999-2019 ENKJ All Rights Reserved 億恩科技 版權(quán)所有  地址:鄭州市高新區(qū)翠竹街1號總部企業(yè)基地億恩大廈  法律顧問:河南亞太人律師事務(wù)所郝建鋒、杜慧月律師   京公網(wǎng)安備41019702002023號
      0
     
     
     
     

    0371-60135900
    7*24小時客服服務(wù)熱線