• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            小默

            [zz]內(nèi)核模塊編程之入門(二)—必備知識(shí)

            模塊編程屬于內(nèi)核編程,因此,除了對(duì)內(nèi)核相關(guān)知識(shí)有所了解外,還需要了解與模塊相關(guān)的知識(shí)。

            1.應(yīng)用程序與內(nèi)核模塊的比較
            為了加深對(duì)內(nèi)核模塊的了解,表一給出應(yīng)用程序與內(nèi)核模塊程序的比較。
            表一 應(yīng)用程序與內(nèi)核模塊程序的比較

              C語言應(yīng)用程序 內(nèi)核模塊程序
            使用函數(shù) Libc 內(nèi)核函數(shù)
            運(yùn)行空間 用戶空間 內(nèi)核空間
            運(yùn)行權(quán)限 普通用戶 超級(jí)用戶
            入口函數(shù) main() module_init()
            出口函數(shù) exit() module_exit()
            編譯 Gcc –c Makefile
            連接 Gcc insmod
            運(yùn)行 直接運(yùn)行 insmod
            調(diào)試 Gdb kdbug, kdb,kgdb

            從表一我們可以看出,內(nèi)核模塊程序不能調(diào)用libc庫中的函數(shù),它運(yùn)行在內(nèi)核空間,且只有超級(jí)用戶可以對(duì)其運(yùn)行。另外,模塊程序必須通過module_init()module-exit()函數(shù)來告訴內(nèi)核“我來了”和“我走了”。

            2內(nèi)核符號(hào)表(如果對(duì)以下第2~4點(diǎn)理解上有困難,可以越過

            如 前所述,Linux內(nèi)核是一個(gè)整體結(jié)構(gòu),像一個(gè)圓球,而模塊是插入到內(nèi)核中的插件。盡管內(nèi)核不是一個(gè)可安裝模塊,但為了方便起見,Linux把內(nèi)核也看作 一個(gè)“母”模塊。那么模塊與模塊之間如何進(jìn)行交互呢,一種常用的方法就是共享變量和函數(shù)。但并不是模塊中的每個(gè)變量和函數(shù)都能被共享,內(nèi)核只把各個(gè)模塊中 主要的變量和函數(shù)放在一個(gè)特定的區(qū)段,這些變量和函數(shù)就統(tǒng)稱為符號(hào)。到低哪些符號(hào)可以被共享? Linux內(nèi)核有自己的規(guī)定。對(duì)于內(nèi)核這個(gè)特殊的母模塊,在kernel/ksyms.c中定義了從中可以“移出”的符號(hào),例如進(jìn)程管理子系統(tǒng)可以“移出”的符號(hào)定義如下:

            /* 進(jìn)程管理 */

            EXPORT_SYMBOL(do_mmap_pgoff);

            EXPORT_SYMBOL(do_munmap);

            EXPORT_SYMBOL(do_brk);

            EXPORT_SYMBOL(exit_mm);

            EXPORT_SYMBOL(schedule);

            EXPORT_SYMBOL(jiffies);

            EXPORT_SYMBOL(xtime);

            你可能對(duì)這些變量和函數(shù)已經(jīng)很熟悉。其中宏定義EXPORT_SYMBOL()本身的含義是“移出符號(hào)”。為什么說是“移出”呢?因?yàn)檫@些符號(hào)本來是內(nèi)核內(nèi)部的符號(hào),通過這個(gè)宏放在一個(gè)公開的地方,使得裝入到內(nèi)核中的其他模塊可以引用它們。

            實(shí)際上,僅僅知道這些符號(hào)的名字是不夠的,還得知道它們?cè)趦?nèi)核地址空間中的地址才有意義。因此,內(nèi)核中定義了如下結(jié)構(gòu)來描述模塊的符號(hào):

            struct module_symbol

            {

            unsigned long value; /*符號(hào)在內(nèi)核地址空間中的地址*/

            const char *name; /*符號(hào)名*/

            };

            我們可以從/proc/ksyms文件中讀取所有內(nèi)核模塊“移出”的符號(hào),這所有符號(hào)就形成內(nèi)核符號(hào)表,其格式如下:

            內(nèi)存地址 符號(hào)名 [所屬模塊]

            在模塊編程中,可以根據(jù)符號(hào)名從這個(gè)文件中檢索出其對(duì)應(yīng)的地址,然后直接訪問該地址從而獲得內(nèi)核數(shù)據(jù)。第三列“所屬模塊”指符號(hào)所在的模塊名,對(duì)于從內(nèi)核這一母模塊移出的符號(hào),這一列為空。

            模塊加載后,2.4內(nèi)核下可通過 /proc/ksyms、 2.6 內(nèi)核下可通過/proc/kallsyms查看模塊輸出的內(nèi)核符號(hào)

            3模塊依賴

            如前所述,內(nèi)核符號(hào)表記錄了所有模塊可以訪問的符號(hào)及相應(yīng)的地址。當(dāng)一個(gè)新的模塊被裝入內(nèi)核后,它所申明的某些符號(hào)就會(huì)被登記到這個(gè)表中,而這些符號(hào)可能被其他模塊所引用,這就引出了模塊依賴這個(gè)問題。

            一個(gè)模塊A引用另一個(gè)模塊B所移出的符號(hào),我們就說模塊B被模塊A引用,或者說模塊A依賴模塊B。如果要鏈接模塊A,必須先鏈接模塊B。這種模塊間相互依賴的關(guān)系就叫模塊依賴。

            4.模塊引用計(jì)數(shù)器

            為 了確保模塊安全地卸載,每個(gè)模塊都有一個(gè)引用計(jì)數(shù)器。當(dāng)執(zhí)行模塊所涉及的操作時(shí)就遞增計(jì)數(shù)器,在操作結(jié)束時(shí)就遞減這個(gè)計(jì)數(shù)器;另外,當(dāng)模塊B被模塊A引用 時(shí),模塊B的引用計(jì)數(shù)就遞增,引用結(jié)束,計(jì)數(shù)器遞減。什么時(shí)候可以卸載這個(gè)模塊?當(dāng)然只有這個(gè)計(jì)數(shù)器值為0的時(shí)候,例如,當(dāng)一個(gè)文件系統(tǒng)還被安裝在系統(tǒng)上 時(shí)就不能將其卸載,當(dāng)這個(gè)文件系統(tǒng)不再被使用時(shí),引用計(jì)數(shù)器就為0,于是可以卸載。

            四.模塊編譯

            Linux 中最重要的軟件開發(fā)工具是 GCCGCC GNU C C++ 編譯器。但是,在大型的開發(fā)項(xiàng)目中,通常有幾十到上百個(gè)的源文件,如果每次均手工鍵入 gcc 命令進(jìn)行編譯的話,則會(huì)非常不方便。因此,人們通常利用 make 工具來自動(dòng)完成編譯工作。利用這種自動(dòng)編譯可大大簡(jiǎn)化開發(fā)工作,避免不必要的重新編譯。這些工作包括:如果僅修改了某幾個(gè)源文件,則只重新編譯這幾個(gè)源文件;如果某個(gè)頭文件被修改了,則重新編譯所有包含該頭文件的源文件。

            1.編譯工具make

            實(shí)際上,make 工具通過一個(gè)稱為 Makefile 的文件來完成并自動(dòng)維護(hù)編譯工作。Makefile 需要按照某種語法進(jìn)行編寫,其中說明了如何編譯各個(gè)源文件并連接生成可執(zhí)行文件,并定義了源文件之間的依賴關(guān)系。下面給出2.6 內(nèi)核模塊的Makefile模板(請(qǐng)參看Makefile的寫法)

             

            # Makefile2.6
            obj-m += hellomod.o        # 產(chǎn)生hellomod 模塊的目標(biāo)文件
            CURRENT_PATH := $(shell pwd)   #模塊所在的當(dāng)前路徑
            LINUX_KERNEL := $(shell uname -r)    #Linux內(nèi)核源代碼的當(dāng)前版本
            LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL) #Linux內(nèi)核源代碼的絕對(duì)路徑
            all:
            make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules   #編譯模塊了
            clean:
            make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean    #清理

            注意: 在每個(gè)命令前(例如make命令前)要鍵入一個(gè)制表符(按TAB鍵產(chǎn)生)

            有了Makefile,執(zhí)行make命令,會(huì)自動(dòng)形成相關(guān)的后綴為.o和.ko文件。
            到此,模塊編譯好了,該把它插入到內(nèi)核了:

            如:$insmod hellomod.ko

              當(dāng)然,要以系統(tǒng)員的身份才能把模塊插入。

              成功插入后,可以通過dmesg命令查看,屏幕最后幾行的輸出就是你程序中輸出的內(nèi)容:Hello,World! from the kernel space…

             
            當(dāng)模塊不再需要時(shí),可以通過rmmod命令移去,例如

            $rmmod hellomod

            posted on 2010-03-29 08:40 小默 閱讀(242) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Linux

            導(dǎo)航

            統(tǒng)計(jì)

            留言簿(13)

            隨筆分類(287)

            隨筆檔案(289)

            漏洞

            搜索

            積分與排名

            最新評(píng)論

            閱讀排行榜

            久久99国产精品久久99果冻传媒 | 天天躁日日躁狠狠久久| 久久精品一区二区| 久久亚洲中文字幕精品有坂深雪| 久久午夜夜伦鲁鲁片免费无码影视| 久久久久国产成人精品亚洲午夜| 99久久精品费精品国产一区二区| 国产精品美女久久久久久2018| 亚洲AV无码久久精品色欲 | 国产69精品久久久久观看软件| 欧美午夜精品久久久久久浪潮| 久久久久国色AV免费看图片| 久久久久无码精品| 国产精品久久久久久久app | 亚洲AV成人无码久久精品老人| 久久婷婷人人澡人人爽人人爱| 一本久久知道综合久久| 久久99国产综合精品免费| 99久久99久久精品国产片| 久久精品国产亚洲Aⅴ蜜臀色欲| 午夜精品久久久久久影视777| 久久综合给合久久狠狠狠97色| 久久久久久亚洲精品成人| 7国产欧美日韩综合天堂中文久久久久| 国产精品成人99久久久久| 久久久久久久97| 美女写真久久影院| 99久久综合国产精品免费| 99久久人妻无码精品系列| 久久国产影院| 久久精品夜夜夜夜夜久久| 久久精品国产一区二区电影| 久久夜色精品国产噜噜亚洲a | 亚洲天堂久久精品| 99久久综合国产精品免费| 久久久久久a亚洲欧洲aⅴ| 久久久亚洲AV波多野结衣| 美女写真久久影院| 久久A级毛片免费观看| 亚洲v国产v天堂a无码久久| 欧美日韩中文字幕久久伊人|