• <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ǔ)言應(yīng)用程序 內(nèi)核模塊程序
            使用函數(shù) Libc庫(kù) 內(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庫(kù)中的函數(shù),它運(yùn)行在內(nèi)核空間,且只有超級(jí)用戶可以對(duì)其運(yùn)行。另外,模塊程序必須通過(guò)module_init()module-exit()函數(shù)來(lái)告訴內(nèi)核“我來(lái)了”和“我走了”。

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

            如 前所述,Linux內(nèi)核是一個(gè)整體結(jié)構(gòu),像一個(gè)圓球,而模塊是插入到內(nèi)核中的插件。盡管內(nèi)核不是一個(gè)可安裝模塊,但為了方便起見(jiàn),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)”。為什么說(shuō)是“移出”呢?因?yàn)檫@些符號(hào)本來(lái)是內(nèi)核內(nèi)部的符號(hào),通過(guò)這個(gè)宏放在一個(gè)公開(kāi)的地方,使得裝入到內(nèi)核中的其他模塊可以引用它們。

            實(shí)際上,僅僅知道這些符號(hào)的名字是不夠的,還得知道它們?cè)趦?nèi)核地址空間中的地址才有意義。因此,內(nèi)核中定義了如下結(jié)構(gòu)來(lái)描述模塊的符號(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)的地址,然后直接訪問(wèn)該地址從而獲得內(nèi)核數(shù)據(jù)。第三列“所屬模塊”指符號(hào)所在的模塊名,對(duì)于從內(nèi)核這一母模塊移出的符號(hào),這一列為空。

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

            3模塊依賴

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

            一個(gè)模塊A引用另一個(gè)模塊B所移出的符號(hào),我們就說(shuō)模塊B被模塊A引用,或者說(shuō)模塊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 中最重要的軟件開(kāi)發(fā)工具是 GCCGCC GNU C C++ 編譯器。但是,在大型的開(kāi)發(fā)項(xiàng)目中,通常有幾十到上百個(gè)的源文件,如果每次均手工鍵入 gcc 命令進(jìn)行編譯的話,則會(huì)非常不方便。因此,人們通常利用 make 工具來(lái)自動(dòng)完成編譯工作。利用這種自動(dòng)編譯可大大簡(jiǎn)化開(kāi)發(fā)工作,避免不必要的重新編譯。這些工作包括:如果僅修改了某幾個(gè)源文件,則只重新編譯這幾個(gè)源文件;如果某個(gè)頭文件被修改了,則重新編譯所有包含該頭文件的源文件。

            1.編譯工具make

            實(shí)際上,make 工具通過(guò)一個(gè)稱為 Makefile 的文件來(lái)完成并自動(dòng)維護(hù)編譯工作。Makefile 需要按照某種語(yǔ)法進(jìn)行編寫,其中說(shuō)明了如何編譯各個(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)員的身份才能把模塊插入。

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

             
            當(dāng)模塊不再需要時(shí),可以通過(guò)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)論

            閱讀排行榜

            久久久久这里只有精品 | 久久无码人妻一区二区三区| 久久中文字幕视频、最近更新| 久久久亚洲欧洲日产国码aⅴ| 99久久成人国产精品免费| 精品久久久久久久| 青青草原综合久久大伊人导航| 精品国产乱码久久久久软件| 久久99国产乱子伦精品免费| 久久伊人色| 亚洲欧美一级久久精品| 国内精品久久久久久99| 日产精品久久久久久久性色| 久久99久国产麻精品66| 国产偷久久久精品专区| 91久久香蕉国产熟女线看| 亚洲欧洲精品成人久久奇米网 | 99久久精品免费观看国产| 久久精品国产半推半就| 精品欧美一区二区三区久久久| 伊人久久大香线焦AV综合影院| 亚洲国产精品无码久久SM| 久久久黄片| 久久精品国产半推半就| 国内精品久久久久国产盗摄| 久久丝袜精品中文字幕| 色综合久久中文字幕无码| 色综合久久88色综合天天| 久久超碰97人人做人人爱| 久久久久综合网久久| 日韩va亚洲va欧美va久久| 狠狠色丁香婷婷久久综合五月| 欧美午夜A∨大片久久| 97精品国产97久久久久久免费| 久久亚洲高清观看| 亚洲日韩欧美一区久久久久我 | 久久精品人妻一区二区三区| 国产精品久久久久久五月尺| 久久精品国产亚洲沈樵| 波多野结衣久久一区二区| 久久97精品久久久久久久不卡|