模塊和編譯內(nèi)核_第1頁(yè)
模塊和編譯內(nèi)核_第2頁(yè)
模塊和編譯內(nèi)核_第3頁(yè)
模塊和編譯內(nèi)核_第4頁(yè)
模塊和編譯內(nèi)核_第5頁(yè)
已閱讀5頁(yè),還剩61頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

編譯內(nèi)核、模塊編程編譯內(nèi)核添加系統(tǒng)調(diào)用模塊編程體會(huì)用戶空間和系統(tǒng)空間學(xué)習(xí)模塊的操作(加載、卸載)本實(shí)驗(yàn)討論內(nèi)容編譯內(nèi)核linux內(nèi)核源碼公開(kāi)。并可以編譯新內(nèi)核。對(duì)redhat9來(lái)說(shuō),內(nèi)核源碼在/usr/src,對(duì)FC7來(lái)說(shuō),在/usr/src/kernels。[root@localhostroot]#cd/usr/src[root@localhost

src]#lsdebuglinux-2.4linux-2.4.20-8redhat[root@localhostsrc]#cd/usr/src/kernels[root@localhostkernels]#ls2.6.11-1.1369_FC4-i686為什么要編譯內(nèi)核學(xué)習(xí)與體會(huì)。需要使用新內(nèi)核中的功能。修補(bǔ)系統(tǒng)新發(fā)現(xiàn)的安全漏洞和缺陷,維護(hù)系統(tǒng)的正常使用和運(yùn)行。提高系統(tǒng)性能,包括升級(jí)新內(nèi)核,修改現(xiàn)有內(nèi)核。硬件發(fā)生變動(dòng),需要在內(nèi)核中進(jìn)行調(diào)整。編譯內(nèi)核的過(guò)程(1)uname–r2.6.11-1到,下載內(nèi)核源碼。linux-.tar.bz2或linux-.tar.gzcplinux-.tar.bz2到/usr/srctarjxvflinux-.tar.bz2解壓。如果是gz文件,則用tarzxvflinux-.tar.gz[root@localhostboot]#cd/usr/src[root@localhost

src]#lskernelslinux-linux-.tar.bz2redhat在FC7上編譯2.6內(nèi)核的過(guò)程(2)內(nèi)核源碼/pub/linux/kernel/v2.6/cp/mnt/hgfs/share/linux-.tar.gz/usr/srctarzxvflinux-.tar.gz[root@localhost

src]#lskernelslinux-linux-.tar.gzredhat[root@localhost

src]#cdlinux-[root@localhostlinux-]#lsarchcryptoincludekernelmmscriptsblockDocumentationinitlibnetsecurityCOPYINGdriversipcMAINTAINERSREADMEsoundCREDITSfs

Kbuild

MakefileREPORTING-BUGSusr在FC7上編譯2.6內(nèi)核的過(guò)程(2)啟動(dòng)文件[root@localhost/]cp–rbootboot1//備份boot目錄,最好要這樣。[root@localhost/]#cdboot1[root@localhostboot1]#lsconfig-2.6.11-1.1369_FC4編譯配置文件

lost+foundgrubSystem.map-2.6.11-1.1369_FC4內(nèi)核符號(hào)表initrd-2.6.11-1.1369_FC4.imgvmlinuz-2.6.11-1.1369_FC4內(nèi)核映像文件initrd是linux在系統(tǒng)引導(dǎo)過(guò)程中使用的一個(gè)臨時(shí)的根文件系統(tǒng),用來(lái)支持兩階段的引導(dǎo)過(guò)程。在內(nèi)核之前進(jìn)入內(nèi)存過(guò)程(3)在源碼中添加系統(tǒng)調(diào)用-調(diào)用過(guò)程系統(tǒng)調(diào)用總控程序地址掛在0x80號(hào)中斷上。通過(guò)0x80號(hào)中斷進(jìn)入總控程序,并通過(guò)寄存器eax傳入系統(tǒng)調(diào)用號(hào)??偪爻绦蛘业较到y(tǒng)調(diào)用向量表sys_call_table(作為基址),再將eax中傳入的系統(tǒng)調(diào)用號(hào)×4B找到對(duì)應(yīng)系統(tǒng)調(diào)用偏移地址(向量表每個(gè)表項(xiàng)占4B),基址+偏移地址即為系統(tǒng)調(diào)用服務(wù)程序入口地址。轉(zhuǎn)到系統(tǒng)調(diào)用服務(wù)程序asmlinkagesys_×××()asmlinkage

表示函數(shù)不通過(guò)寄存器,而是通過(guò)堆棧獲得并修改參數(shù)。過(guò)程(3)在源碼中添加系統(tǒng)調(diào)用[root@localhostlinux-]#vikernel/sys.c在尾部添加:asmlinkage

int

testprint(char*str){

printk("mynameis%s\n",str);return0;}過(guò)程(3)在源碼中添加系統(tǒng)調(diào)用[root@localhostlinux-]#viarch/i386/kernel/syscall_table.S.longsys_tee/*315*/.longsys_vmsplice.longsys_move_pages.longsys_getcpu.longsys_epoll_pwait.longsys_testprint/*320*/過(guò)程(3)在源碼中添加系統(tǒng)調(diào)用[root@localhostlinux-]#viinclude/asm-i386/unistd.h#defineNR_syscalls320#define__NR_epoll_pwait319#define__NR_testprint320#ifdef__KERNEL__#defineNR_syscalls321在FC7上編譯2.6內(nèi)核的過(guò)程(4)編譯過(guò)程makemrproper:清除過(guò)去編譯留下的中間文件,若是第一次編譯的新內(nèi)核,可以不要這一步。配置編譯選項(xiàng):用makemenuconfig等,產(chǎn)生編譯配置文件.config產(chǎn)生內(nèi)核映像文件bzImage。并將其放到/boot目錄產(chǎn)生可加載模塊。并將它們加入到/lib/modules目錄。產(chǎn)生System.map文件等文件,將其放到/boot目錄。#makeconfig:基于文本的最為傳統(tǒng)的配置界面,不推薦使用#makemenuconfig:基于文本菜單的配置界面,字符終端下推薦使用#makexconfig:基于圖形窗口模式的配置界面,Xwindow下推薦使用#makeoldconfig:如果只想在原來(lái)內(nèi)核配置的基礎(chǔ)上修改一些小地方,用此方法會(huì)省去不少麻煩上述幾種方法的目的是一樣的,那就是生成一個(gè).config文件常用的編譯配置方式:選擇相應(yīng)的配置時(shí),有三種選擇,它們分別代表的含義如下:Y--將該功能編譯進(jìn)內(nèi)核N--不將該功能編譯進(jìn)內(nèi)核M--將該功能編譯成可以在需要時(shí)動(dòng)態(tài)插入到內(nèi)核中的模塊可用空格鍵在這三者之間切換?;虬磞/m/n進(jìn)行選擇方括號(hào):只有*、空(不編譯)兩種選擇尖括號(hào):可以是空,"*"和"M"圓括號(hào):在提供的幾項(xiàng)中選擇按兩次ESC鍵可退出;或選擇EXIT用menuconfig方式:#makedep

鏈接程序代碼與函數(shù)庫(kù);實(shí)際上讀取配置過(guò)程生成的配置文件,來(lái)創(chuàng)建對(duì)應(yīng)于配置的依賴關(guān)系樹(shù),從而決定哪些需要編譯而那些不需要;#makeclean刪除前面步驟產(chǎn)生的不必要的文件;#makebzImage

開(kāi)始編譯產(chǎn)生內(nèi)核映像文件;makeall相當(dāng)于:#makemodules編譯模塊;#makemodules_install

安裝編譯完成的模塊。makeinstall安裝編譯完成的模塊。將bzImage、System.map

復(fù)制到/boot繼續(xù)操作整個(gè)編譯過(guò)程(1)[root@localhost/]cp–rbootboot1//備份boot目錄[root@localhostlinux-]#makemrproper[root@localhostboot]#cp/boot/config-2.6.21-1.3194.fc7/usr/src/linux-[root@localhostlinux-]#mvconfig-2.6.21-1.3194.fc7.config[root@localhostlinux-]#makeoldconfig[root@localhostlinux-]#viMakefileVERSION=2PATCHLEVEL=6SUBLEVEL=21EXTRAVERSION=.6改為:EXTRAVERSION=.6-jiangjian整個(gè)編譯過(guò)程(2)[root@localhostlinux-]#makeallNAME=NocturnalMonsterPuppyLDvmlinuxSYSMAPSystem.mapSYSMAP.tmp_System.mapBUILDarch/i386/boot/bzImageRootdeviceis(253,0)Bootsector512bytes.Setupis7353bytes.Systemis1801kBKernel:arch/i386/boot/bzImageisready(#1)整個(gè)編譯過(guò)程(3)[root@localhostlinux-]#makemodules_install[root@localhostlinux-]#makeinstallsh/usr/src/linux-/arch/i386/boot/install.sh-jiangjianarch/i386/boot/bzImageSystem.map"/boot“[root@localhostlinux-]#vi/boot/grub/menu.lst#hiddenmenu[root@localhostlinux-]#reboot在FC7上編譯2.6內(nèi)核的過(guò)程說(shuō)明(1)[root@localhostboot]#cdlinux-[root@localhost

linux-]#makemrproper

用來(lái)保證新內(nèi)核樹(shù)無(wú)殘留.o或是其他附屬文件;第一次編譯可以不用。[root@localhost/]cp–rbootboot1//備份boot目錄。[root@localhost/]#cdboot1[root@localhostboot1]#lsconfig-2.6.11-1.1369_FC4編譯配置文件

lost+foundgrubSystem.map-2.6.11-1.1369_FC4內(nèi)核符號(hào)表initrd-2.6.11-1.1369_FC4.imgvmlinuz-2.6.11-1.1369_FC4內(nèi)核映像文件在FC7上編譯2.6內(nèi)核的過(guò)程說(shuō)明(2)[root@localhostboot]#cd/boot[rootboot]#cpconfig-2.6.11-1.1369_FC4/usr/src/linux-/.config[root

linux-]#makeoldconfig

接著修改新源代碼目錄/usr/src/linux-/下的Makefile文件。將EXTRAVERSION=.1改為EXTRAVERSION=.1-jiangjian在新內(nèi)核源碼目錄/usr/src/linux-/下:#makeall//最關(guān)鍵最長(zhǎng)的一步,就是編譯產(chǎn)生內(nèi)核映像和模塊。#makemodules_install

//將模塊安裝到/lib/modules/<內(nèi)核版本號(hào)>#makeinstall//將內(nèi)核映像等文件復(fù)制到/boot,并修改引導(dǎo)程序grub的配置。在FC7上編譯2.6內(nèi)核的過(guò)程說(shuō)明(3)[root@localhostboot]#lsconfig-2.6.11-1.1369_FC4System.map-2.6.11-1.1369_FC4grubSystem.map--jiangjianinitrd-2.6.11-1.1369_FC4.imgvmlinuzinitrd--jiangjian.imgvmlinuz-2.6.11-1.1369_FC4lost+foundvmlinuz--jiangjianSystem.map[root@localhostboot]#llvmlinuzlrwxrwxrwx1rootroot2611月2417:05vmlinuz->vmlinuz--jiangjian[root@localhostboot]#ll

System.maplrwxrwxrwx1rootroot2911月2417:05System.map->System.map--jiangjian在FC7上編譯2.6內(nèi)核的過(guò)程說(shuō)明(4)[root@localhostboot]#vi/boot/grub/menu.lst

(RH9是grub.conf)修改grub配置文件在hiddenmenu上加注釋符#,注釋掉該句(RH9不需要)#reboot

//重啟,從新內(nèi)核啟動(dòng)[root@localhost~]#uname-r-jiangjian啟動(dòng)后,查看內(nèi)核版本:修改后的/boot/grub/menu.lst

#grub.confgeneratedbyanaconda##Notethatyoudonothavetorerungrubaftermakingchangestothisfile#NOTICE:Youhavea/bootpartition.Thismeansthat#allkernelandinitrdpathsarerelativeto/boot/,eg.#root(hd0,0)#kernel/vmlinuz-versionroroot=/dev/VolGroup00/LogVol00#initrd/initrd-version.img#boot=/dev/sdadefault=1timeout=10splashimage=(hd0,0)/grub/splash.xpm.gz#hiddenmenutitleFedoraCore(-jiangjian) root(hd0,0) kernel/vmlinuz--jiangjianroroot=/dev/VolGroup00/LogVol00rhgbquiet initrd/initrd--jiangjian.imgtitleFedoraCore(2.6.11-1.3194.fc7) root(hd0,0) kernel/vmlinuz-2.6.11-1.1369_FC4roroot=/dev/VolGroup00/LogVol00rhgbquiet initrd/initrd-2.6.11-1.1369_FC4.img在FC7上編譯2.6內(nèi)核的過(guò)程說(shuō)明(5)在新內(nèi)核測(cè)試新添加的系統(tǒng)調(diào)用sys_testprint()[root@localhost~]#uname-r-jiangjian[root@localhost~]#cattestprint.c#include<unistd.h>#include<sys/syscall.h>#include<stdio.h>intmain(){

intret;ret=syscall(320,"jiangjian");

printf("returnvalueis%d\n",ret);return0;}在新內(nèi)核測(cè)試新添加的系統(tǒng)調(diào)用sys_testprint()[root@localhost~]#gcc

testprint.c-otestprint[root@localhost~]#./testprintreturnvalueis0[root@localhost~]#dmesgmynameisjiangjian模塊編程模塊是linux操作系統(tǒng)的特有機(jī)制??梢栽诓恍枰獙?duì)內(nèi)核進(jìn)行重新編譯和引導(dǎo)的情況下,動(dòng)態(tài)地加載和卸載模塊,也就是所謂LKM(可加載模塊,LoadableKernelModules)。將該模塊作為linux內(nèi)核空間的擴(kuò)展來(lái)執(zhí)行。通過(guò)insmod命令手工加載,通過(guò)rmmod來(lái)手工卸載。內(nèi)核也可以通過(guò)守護(hù)進(jìn)程kerneld動(dòng)態(tài)加載和卸載模塊。嵌入式系統(tǒng)等采用微內(nèi)核。UNIX系統(tǒng)采用宏內(nèi)核。linux采用折衷方案,內(nèi)核實(shí)現(xiàn)最基本功能,其他部分采用模塊方式,根據(jù)需要加載模塊。模塊工作在內(nèi)核空間。微內(nèi)核和宏內(nèi)核模塊工作在內(nèi)核空間。模塊是一個(gè)目標(biāo)文件(*.o,在2.6內(nèi)核中是.ko),不能單獨(dú)運(yùn)行。不是一個(gè)獨(dú)立的進(jìn)程。模塊由一組函數(shù)和數(shù)據(jù)結(jié)構(gòu)組成,作為獨(dú)立程序編譯??梢圆捎脛?dòng)態(tài)加載或是靜態(tài)加載。不能使用c庫(kù)函數(shù),只能使用內(nèi)核函數(shù),比如不能用printf,只能用printk()。內(nèi)核??臻g有限,一般4KB到8KB,所以不要定義過(guò)多自動(dòng)變量,如需要大的結(jié)構(gòu),建議使用動(dòng)態(tài)分配的空間。不能進(jìn)行浮點(diǎn)運(yùn)算。模塊的特性內(nèi)核符號(hào)表管理。內(nèi)核將資源登記在符號(hào)表(symboltable)中,模塊加載時(shí),模塊就可以通過(guò)內(nèi)核符號(hào)表使用內(nèi)核的資源,解決資源引用問(wèn)題。Linux支持模塊堆棧(modulestacking)的概念,一個(gè)模塊可以請(qǐng)求其他模塊為之服務(wù)。同時(shí),當(dāng)通過(guò)init_module()調(diào)用加載新模塊時(shí),該模塊定義的符號(hào)(包括函數(shù)和全局變量等),此時(shí)也被導(dǎo)出,供其他以后可能加載的模塊使用。Linux內(nèi)核對(duì)加載的內(nèi)核模塊進(jìn)行管理內(nèi)核符號(hào)表管理。通過(guò)/proc/ksyms文件(在2.6內(nèi)核中是/proc/kallsyms),可以查看內(nèi)核符號(hào)表中各類(lèi)符號(hào)及其地址。如:Linux內(nèi)核對(duì)加載的內(nèi)核模塊進(jìn)行管理[root@localhostsimple]#cat/proc/ksyms|grepprintkc011c2a0printk_R1b7d4074c03d7b88tux_Dprintk_Ra12c9a12c03d7b84tux_TDprintk_Rc0ce7778維持內(nèi)核模塊的引用計(jì)數(shù)。引用數(shù)為0才允許卸載該模塊。Linux內(nèi)核對(duì)加載的內(nèi)核模塊進(jìn)行管理[root@localhostsimple]#lsmod|tail-4jbd518922[ext3]BusLogic1007963sd_mod134528scsi_mod1071283[usb-storageBusLogicsd_mod]模塊名稱模塊大小引用計(jì)數(shù)。lsmod(listmodules)用來(lái)查看當(dāng)前內(nèi)核加載的模塊最小的模塊結(jié)構(gòu)也必須包括兩個(gè)函數(shù):init_modules():加載模塊時(shí)被調(diào)用,可以啟動(dòng)模塊加載期間的操作;cleanup_modules():卸載模塊時(shí)被調(diào)用,停止相關(guān)操作。模塊通過(guò)加入新函數(shù)來(lái)實(shí)現(xiàn)期望的功能,每個(gè)新函數(shù)必須在該模塊加載到內(nèi)核中時(shí)進(jìn)行注冊(cè),在模塊卸載時(shí)注銷(xiāo);注冊(cè)在init_modules()中完成;注銷(xiāo)在cleanup_modules()中完成。模塊的組織結(jié)構(gòu)(2.4內(nèi)核)#include<linux/module.h>//聲明是一個(gè)模塊#include<linux/kernel.h>//說(shuō)明是個(gè)內(nèi)核功能int

init_module()//用到了module.h{...//加載時(shí),初始化模塊的編碼} //read()、ioctl()等函數(shù)...voidcleanup_module()//用到了module.h{...//卸載時(shí),注銷(xiāo)模塊的編碼}初步印象:沒(méi)有main函數(shù)#gcc?O2?Wall?DMODULE?D_KERNEL_?c

filename.c

filename.c為自己編寫(xiě)的模塊程序源代碼文件-Wall顯示所有的警告消息,發(fā)生警報(bào)時(shí)取消編譯,即將警報(bào)看作出錯(cuò);

?Dmacro:其功能類(lèi)似于在源碼中的#define;-O2:對(duì)編譯進(jìn)行優(yōu)化,比-O更好的優(yōu)化,編譯速度較之更慢一些,但產(chǎn)生可執(zhí)行文件的執(zhí)行速度更快;-g:產(chǎn)生調(diào)試信息,gcc允許-g和-O2同時(shí)使用。KERNEL前后各有兩個(gè)短橫杠。模塊的編譯許多情況下,頭文件和源文件會(huì)單獨(dú)存放在不同的目錄中。例如,假設(shè)存放源文件的子目錄名為./src,而包含文件則放在層次的其他目錄下,如./inc。當(dāng)我們?cè)?/src

目錄下進(jìn)行編譯工作時(shí),如何告訴GCC到哪里找頭文件呢?方法如下所示:

$gcc

test.c–I../inc-otest

上面的命令告訴GCC包含文件存放在./inc目錄下,在當(dāng)前目錄的上一級(jí)。如果在編譯時(shí)需要的包含文件存放在多個(gè)目錄下,可以使用多個(gè)-I來(lái)指定各個(gè)目錄:

$gcc

test.c–I../inc–I../../inc2-otest

這里指出了另一個(gè)包含子目錄inc2,較之前目錄它還要在再上兩級(jí)才能找到。lsmod:查看加載的模塊,實(shí)際使用的是/proc/modules文件。insmod:加載模塊。rmmod;卸載模塊。dmesg:查看日志信息。實(shí)際上是用/var/log/messages文件。以上命令只能由超級(jí)用戶執(zhí)行。產(chǎn)生模塊文件以后的操作模塊的加載方式:用insmod手工加載模塊;請(qǐng)求kerneld加載。insmod在/lib/modules/kernel-version中找到請(qǐng)求加載的模塊,然后執(zhí)行:

create_module(),init_module()執(zhí)行完insmod后,用dmesg查看日志,然后可以在/proc/modules文件中看到加載的模塊?;蚴鞘褂胠smod查看。模塊的加載

模塊的卸載:用rmmod卸載模塊;cleanup_module()斷開(kāi)內(nèi)核模塊鏈表中的鏈接。模塊的卸載該模塊只要兩個(gè)函數(shù):init_module()cleanup_module()編寫(xiě)一個(gè)簡(jiǎn)單的內(nèi)核模塊#defineMODULE//MODULE需要寫(xiě)在module.h之前#include<linux/kernel.h>//表示內(nèi)核模塊,printk需要#include<linux/module.h>//一個(gè)模塊,init_module等需要//處理CONFIG_MODVERSIONS

#ifCONFIG_MODVERSIONS==1#defineMODVERSIONS#include<linux/modversions.h>#endif

int

init_module()//初始化模塊

{

printk("Hello!Thisisatestingmodule!\n");return0;}voidcleanup_module()//取消init_module()函數(shù)所做的操作

{

printk("Sorry!Thetestingmoduleisunloadingnow!\n");}

[root@linux/]#gcc–O2–Wall–DMODULE–D__KERNEL__?c-I/usr/src/linux/include/simple_module.c[root@linux/]#ls

//在當(dāng)前目錄下查看生成的目標(biāo)文件testmodule.o

[root@linux/]#insmod–f

testmodule.o

//-f表示強(qiáng)行加載,為什么?

Hello!Thisisatestingmodule!

[root@linux/]#rmmodtestmodule

Sorry!Thetestingmoduleisunloadingnow!模塊的加載和卸載報(bào)“gcc和linux內(nèi)核版本沖突”,解決方法:1.使用insmod–f強(qiáng)行加載2.修改/usr/include/linux/version.h:將2.4.20改為2.4.20-8報(bào)“MODULE重復(fù)定義”,為什么?解決方法:1.去掉源程序中的”defineMODULE”2.去掉編譯選項(xiàng)的“-DMODULE”printk()在純字符界面(純console)上有輸出,但是在圖形界面的模擬終端無(wú)輸出。此程序注意三個(gè)問(wèn)題上面的程序執(zhí)行結(jié)果(1)[root@localhostsimple]#lsmakefile

simple_module.c

simple_module.o[root@localhostsimple]#lsmod|grep

simple_module[root@localhostsimple]#cat/proc/modules|grep

simple_module[root@localhostsimple]#insmodsimple_moduleinsmod:simple_module:nomodulebythatnamefound[root@localhostsimple]#insmodsimple_module.oWarning:loadingsimple_module.owilltaintthekernel:nolicenseSeehttp:///lkml/#export-taintedforinformationabouttaintedmodulesModulesimple_moduleloaded,withwarningsinsmod要加*.o上面的程序執(zhí)行結(jié)果(2)[root@localhostsimple]#lsmod|grep

simple_modulesimple_module8920(unused)[root@localhostsimple]#cat/proc/modules|grep

simple_modulesimple_module8920(unused)[root@localhostsimple]#dmesg|tail-1Hello!Thisisatestingmodule!上面的程序執(zhí)行結(jié)果(3)[root@localhostsimple]#rmmodsimple_module.ormmod:modulesimple_module.oisnotloaded[root@localhostsimple]#rmmodsimple_module[root@localhostsimple]#lsmod|grep

simple_module[root@localhostsimple]#dmesg|tail-2Hello!Thisisatestingmodule!Sorry!Thetestingmoduleisunloadingnow![root@localhostsimple]#grepSorry/var/log/messagesNov2501:45:32localhostkernel:Sorry!Thetestingmoduleisunloadingnow!rmmod不要加*.o另外注意lsmod和/proc/modules的關(guān)系:實(shí)際上lsmod就是查看/proc/modules[root@localhostsimple]#cat/proc/modulessimple_module8920(unused)vmblock119524vmxnet127160(unused)vmmemctl80040(unused)vmhgfs474241nls_iso8859-135161(autoclean)nls_cp43751161(autoclean)vfat130041(autoclean)fat388080(autoclean)[vfat]注意:寄存器cr3用于存放當(dāng)前進(jìn)程的“頁(yè)表目錄結(jié)構(gòu)”,訪問(wèn)該寄存器須在內(nèi)核空間進(jìn)行。再看一個(gè)復(fù)雜的例子,看出模塊在內(nèi)核空間工作的特點(diǎn)。#include<stdio.h>voidGetCr3(){

int

iValue;__asm____volatile__("movl%%cr3,%0":"=r"(iValue));

printf("thevalueofcr3is:%d",iValue);}intmain(){GetCr3();return0;}用戶模式下,程序出錯(cuò)!#defineMODULE#include<linux/module.h>int

init_module(){

int

iValue;__asm____volatile__("movl%%cr3,%0":"=r"(iValue));printk("Cr3:%d\n",iValue);return0;}voidcleanup_module(){

printk("UninstallGetCr3.\n");}采用模塊實(shí)現(xiàn)上一實(shí)驗(yàn)沒(méi)有實(shí)現(xiàn)的功能__asm____volatile__("movl%%cr3,%0":"=r"(iValue));printk("Cr3:%d\n",iValue);CR3:內(nèi)存頁(yè)面目錄信息;movx

source,destination:GNU匯編器使用AT&T語(yǔ)法,其中源和目的操作數(shù)的順序和Intel順序是相反的;x如果是l/w/b,分別代表32位長(zhǎng)字/16位字值/8位字節(jié)值;內(nèi)聯(lián)匯編(inlineassembly):將匯編語(yǔ)言函數(shù)直接放在c和c++語(yǔ)言程序中;本來(lái)用asm(“assemblycode”),但是ANSIC中asm另有他用,所以按ANSIC約定編碼,必須使用__asm__替換關(guān)鍵字asm;__volatile__表示不希望編譯器優(yōu)化內(nèi)聯(lián)匯編代碼。__asm____volatile__("movl%%cr3,%0":"=r"(iValue));基本asm格式有缺陷:所有輸入值和輸出值必須使用c程序的全局變量,不能在asm段中使用局部變量;另外內(nèi)聯(lián)代碼中不能改變?nèi)魏渭拇嫫鞯闹担ㄈ绻a中有改變,代碼前后要有保存和恢復(fù)寄存器的操作)采用擴(kuò)展asm格式,此時(shí)必須采用新格式:asm(“assembly

code”:output

location:input

operands:changedregisters)輸出位置:包含內(nèi)聯(lián)匯編代碼的輸出值的寄存器和內(nèi)存地址的列表。輸出和輸入值列表的格式:”constraint”(variable)variable是程序中聲明的變量名;”=“表示只能寫(xiě)入操作數(shù),variable是個(gè)輸出值;”r”表示通過(guò)任何可用的通用寄存器;%0表示第一個(gè)輸出值內(nèi)存地址或是對(duì)應(yīng)寄存器。%1表示下一個(gè)輸出值,依次類(lèi)推。__asm____volatile__("movl%%cr3,%0":"=r"(iValue));Linux下的AT&T語(yǔ)法(即GNUas匯編語(yǔ)法)起源于AT&T貝爾實(shí)驗(yàn)室,是在當(dāng)時(shí)用于實(shí)現(xiàn)Unix系統(tǒng)的處理器操作碼語(yǔ)法之上而形成的,AT&T語(yǔ)法和Intel語(yǔ)法主要區(qū)別如下:AT&T使用$表示立即數(shù),Intel不用,因此表示十進(jìn)制2時(shí)。AT&T為$2,而Intel就是2。AT&T在寄存器前加%,比如eax寄存器表示為%eaxAT&T處理操作數(shù)的順序和Intel相反,比如,movl%eax,%ebx是將eax中的值傳遞給ebx,而Intel是這樣的mov

ebx,eaxAT&T在助記符的后面加上一個(gè)單獨(dú)字符表示操作中數(shù)據(jù)的長(zhǎng)度,比如movl$foo,%eax等同于Intel的mov

eax,wordptr

fooDFLAGS=-D_KERNEL_-DMODULE-I/usr/src/linux/includeGetCr3.o:GetCr3.c

gcc-c$(DFLAGS)GetCr3.cclean:

rm-f*.oMakefile文件注意:編譯后,加載模塊insmodGetCr3.c時(shí),報(bào)“Warning:loadingGetCr3.owilltaintthekernel:nolicense”,在GetCr3.c程序中加”MODULE_LICENSE(“GPL”)”,詳見(jiàn)教材P302。模塊程序和普通程序比較普通程序模塊程序入口和出口main()init_module()cleanup_module()編譯鏈接gccgcc–c–D__KERNEL__-DMDULE運(yùn)行直接運(yùn)行insmod調(diào)試gdbkdb

kgdb

2.6內(nèi)核模塊編程#include<linux/init.h>#include<linux/module.h>MODULE_LICENSE("GPL");staticint

hello_init(void){

printk(KERN_ALERT"hello,world!\n");return0;}staticvoidhello_exit(void){

printk(KERN_ALERT"goodbye!\n");return;}

module_init(hello_init);module_exit(hello_exit);#include<linux/init.h>#include<linux/module.h>MODULE_LICENSE("GPL");staticint

hello_init(void){

printk(KERN_ALERT"hello,world!\n");return0;}staticvoidhello_exit(void){

printk(KERN_ALERT"goodbye!\n");return;}

module_init(hello_init);module_exit(hello_exit);KERN_ALERT用于需要立即采取動(dòng)作的情況。之所以把優(yōu)先級(jí)定得較高,是怕無(wú)法輸出到控制臺(tái)。和后面的字符串之間不能有逗號(hào)。最好以“\n”結(jié)尾printk()和printf()最大的不同點(diǎn)在于不支持浮點(diǎn)數(shù)。2.4內(nèi)核模塊的編譯只需要內(nèi)核源碼頭文件,產(chǎn)生的模塊文件為*.o;2.6內(nèi)核模塊的編譯需要配置過(guò)的內(nèi)核源碼,產(chǎn)生的模塊文件為*.ko;2.4內(nèi)核中默認(rèn)非靜態(tài)全局變量和函數(shù)在模塊加載之后會(huì)輸出到內(nèi)核符號(hào)表中去。2.6內(nèi)核中不會(huì),如果輸出符號(hào),要用:EXPORT_SYMBOL(name)EXPORT_SYMBOL_GPL(name)2.6內(nèi)核模塊編程和2.4內(nèi)核的不同之處2.6內(nèi)核模塊編程-Makefile文件ifneq($(KERNELRELEASE),)obj-m:=hello.oelseKERNELDIR?=/lib/modules/$(shelluname-r)/buildPWD:=$(shellpwd)default: $(MAKE)-C$(KERNELDIR)M=$(PWD)modulesclean: $

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論