




已閱讀5頁,還剩19頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
以下是凌陽教育的嵌入式linux培訓(xùn)資深講師-徐老師提供的免費(fèi)的linux驅(qū)動基礎(chǔ)開發(fā)教程(linux驅(qū)動基礎(chǔ)開發(fā)0- linux驅(qū)動基礎(chǔ)開發(fā)3)理論加實(shí)例詳解,重點(diǎn)紅字標(biāo)注。linux初學(xué)者必看!一:linux驅(qū)動基礎(chǔ)開發(fā)0-linux 設(shè)備驅(qū)動概述目前,Linux軟件工程師大致可分為兩個層次:(1)Linux應(yīng)用軟件工程師(Application Software Engineer):主要利用C庫函數(shù)和Linux API進(jìn)行應(yīng)用軟件的編寫;從事這方面的開發(fā)工作,主要需要學(xué)習(xí):符合linux posix標(biāo)準(zhǔn)的API函數(shù)及系統(tǒng)調(diào)用,linux的多任務(wù)編程技巧:多進(jìn)程、多線程、進(jìn)程間通信、多任務(wù)之間的同步互斥等,嵌入式數(shù)據(jù)庫的學(xué)習(xí),UI編程:QT、miniGUI等。(2)Linux固件工程師(Firmware Engineer):主要進(jìn)行Bootloader、Linux的移植及Linux設(shè)備驅(qū)動程序的設(shè)計工作。一般而言,固件工程師的要求要高于應(yīng)用軟件工程師的層次,而其中的Linux設(shè)備驅(qū)動編程又是Linux程序設(shè)計中比較復(fù)雜的部分,究其原因,主要包括如下幾個方面:1)設(shè)備驅(qū)動屬于Linux內(nèi)核的部分,編寫Linux設(shè)備驅(qū)動需要有一定的Linux操作系統(tǒng)內(nèi)核基礎(chǔ);需要了解部分linux內(nèi)核的工作機(jī)制與系統(tǒng)組成。2)編寫Linux設(shè)備驅(qū)動需要對硬件的原理有相當(dāng)?shù)牧私?,大多?shù)情況下我們是針對一個特定的嵌入式硬件平臺編寫驅(qū)動的,例如:針對特定的主機(jī)平臺:可能是三星的2410、2440,也可能是atmel的,或者飛思卡爾的等等。3)Linux設(shè)備驅(qū)動中廣泛涉及到多進(jìn)程并發(fā)的同步、互斥等控制,容易出現(xiàn)bug;因為linux本身是一個多任務(wù)的工作環(huán)境,不可避免的會出現(xiàn)在同一時刻對同一設(shè)備發(fā)生并發(fā)操作。4)由于屬于內(nèi)核的一部分,Linux設(shè)備驅(qū)動的調(diào)試也相當(dāng)復(fù)雜。linux設(shè)備驅(qū)動沒有一個很好的IDE環(huán)境進(jìn)行單步、變量查看等調(diào)試輔助工具;linux驅(qū)動跟linux內(nèi)核工作在同一層次,一旦發(fā)生問題,很容易造成內(nèi)核的整體崩潰。本系列文章我們將一步步、深入淺出的介紹linux設(shè)備驅(qū)動編程中設(shè)計的一些問題及學(xué)習(xí)方法,希望對大家學(xué)習(xí)linux設(shè)備驅(qū)動有所幫助。在任何一個計算機(jī)系統(tǒng)中,大至服務(wù)器、PC機(jī)、小至手機(jī)、mp3/mp4播放器,無論是復(fù)雜的大型服務(wù)器系統(tǒng)還是一個簡單的流水燈單片機(jī)系統(tǒng),都離不開驅(qū)動程序的身影,沒有硬件的軟件是空中樓閣,沒有軟件的硬件只是一堆廢鐵,硬件是底層的基礎(chǔ),是所有軟件得以運(yùn)行的平臺,代碼最終會落實(shí)到硬件上的邏輯組合。但是硬件與軟件之間存在一個駁論:為了快速、優(yōu)質(zhì)的完成軟件功能設(shè)計,應(yīng)用程序工程師不想也不愿關(guān)心硬件,而硬件工程師也很難有功夫去處理軟件開發(fā)中的一些應(yīng)用。例如軟件工程師在調(diào)用printf的時候,不許也不用關(guān)心信息到底是通過什么樣的處理,走過哪些通路顯示在該顯示的地方,硬件工程師在寫完了一個4*4鍵盤驅(qū)動后,無需也不必管應(yīng)用程序在獲得鍵值后做哪些處理及操作。也就是說軟件工程師需要看到一個沒有硬件的純軟件世界,硬件必須透明的提供給他,誰來實(shí)現(xiàn)這一任務(wù)?答案是驅(qū)動程序,驅(qū)動程序從字面解釋就是:“驅(qū)使硬件設(shè)備行動”。驅(qū)動程序直接與硬件打交道,按照硬件設(shè)備的具體形式,驅(qū)動設(shè)備的寄存器,完成設(shè)備的輪詢、中斷處理、DMA通信,最終讓通信設(shè)備可以收發(fā)數(shù)據(jù),讓顯示設(shè)備能夠顯示文字和畫面,讓音頻設(shè)備可以完成聲音的存儲和播放。2.模塊卸載函數(shù)可見,設(shè)備驅(qū)動程序充當(dāng)了硬件和軟件之間的樞紐,因此驅(qū)動程序的表現(xiàn)形式可能就是一些標(biāo)準(zhǔn)的、事先協(xié)定好的API函數(shù),驅(qū)動工程師只需要去完成相應(yīng)函數(shù)的填充,應(yīng)用工程師只需要調(diào)用相應(yīng)的接口完成相應(yīng)的功能。無論有沒有操作系統(tǒng),驅(qū)動程序都有其存在價值,只是在裸機(jī)情況下,工作環(huán)境比較簡單、完成的工作較單一,驅(qū)動程序完成的功能也就比較簡單,同時接口只要在小范圍內(nèi)符合統(tǒng)一的標(biāo)準(zhǔn)即可。但是在有操作系統(tǒng)的情況下,此問題就會被放大:硬件來自不同的公司、千變?nèi)f化,全世界每天都會有大量的新芯片被生產(chǎn),大量的電路板被設(shè)計出來,如果沒有一個很好的統(tǒng)一標(biāo)準(zhǔn)去規(guī)范這一程序,操作系統(tǒng)就會被設(shè)計的非常冗余,效率會非常低。所以無論任何操作系統(tǒng)都會制定一套標(biāo)準(zhǔn)的架構(gòu)去管理這些驅(qū)動程序:linux作為嵌入式操作系統(tǒng)的典范,其驅(qū)動架構(gòu)具有很高的規(guī)范性與聚合性,不但把不同的硬件設(shè)備分門別類、綜合管理,并且針對不同硬件的共性進(jìn)行了統(tǒng)一抽象,將其硬件相關(guān)性降到最低,大大簡化了驅(qū)動程序的編寫,形成了具有其特色的驅(qū)動組織架構(gòu)。下圖反映了應(yīng)用程序、linux內(nèi)核、驅(qū)動程序、硬件的關(guān)系。 linux內(nèi)核分為5大部分:多任務(wù)管理、內(nèi)存管理、文件系統(tǒng)管理、設(shè)備管理、網(wǎng)絡(luò)管理;每一部分都有承上下的作用,對上提供API接口,提供給應(yīng)用開發(fā)工程師使用;對下通過驅(qū)動程序屏蔽不同的硬件構(gòu)成,完成硬件的具體操作。二:linux驅(qū)動基礎(chǔ)開發(fā)1linux 設(shè)備驅(qū)動基本概念學(xué)習(xí)linux設(shè)備驅(qū)動首先我們必須明確以下幾個概念,為我們接下來學(xué)習(xí)linux驅(qū)動打下堅實(shí)的基礎(chǔ):應(yīng)用程序、庫、內(nèi)核、驅(qū)動程序的關(guān)系:設(shè)備類型設(shè)備文件、主設(shè)備號與從設(shè)備號驅(qū)動程序與應(yīng)用程序的區(qū)別用戶態(tài)與內(nèi)核態(tài)Linux驅(qū)動程序功能一、應(yīng)用程序、庫、內(nèi)核、驅(qū)動程序的關(guān)系1)應(yīng)用程序調(diào)用一系列函數(shù)庫,通過對文件的操作完成一系列功能:應(yīng)用程序以文件形式訪問各種硬件設(shè)備(linux特有的抽象方式,把所有的硬件訪問抽象為對文件的讀寫、設(shè)置)函數(shù)庫:部分函數(shù)無需內(nèi)核的支持,由庫函數(shù)內(nèi)部通過代碼實(shí)現(xiàn),直接完成功能部分函數(shù)涉及到硬件操作或內(nèi)核的支持,由內(nèi)核完成對應(yīng)功能,我們稱其為系統(tǒng)調(diào)用2)內(nèi)核處理系統(tǒng)調(diào)用,根據(jù)設(shè)備文件類型、主設(shè)備號、從設(shè)備號(后面會講解),調(diào)用設(shè)備驅(qū)動程序;3)設(shè)備驅(qū)動直接與硬件通信; 二、設(shè)備類型硬件是千變?nèi)f化的,沒有八千也有一萬了,就像世界上有三種人:男人、女人、女博士一樣,linux做了一個很偉大也很艱難的分類:把所有的硬件設(shè)備分為三大類:字符設(shè)備、塊設(shè)備、網(wǎng)絡(luò)設(shè)備。1) 字符設(shè)備:字符(char)設(shè)備是個能夠像字節(jié)流(類似文件)一樣被訪問的設(shè)備。對字符設(shè)備發(fā)出讀/寫請求時,實(shí)際的硬件I/O操作一般緊接著發(fā)生;字符設(shè)備驅(qū)動程序通常至少要實(shí)現(xiàn)open、close、read和write系統(tǒng)調(diào)用。比如我們常見的lcd、觸摸屏、鍵盤、led、串口等等,就像男人是用來干活的一樣,他們一般對應(yīng)具體的硬件都是進(jìn)行出具的采集、處理、傳輸。2) 塊設(shè)備:一個塊設(shè)備驅(qū)動程序主要通過傳輸固定大小的數(shù)據(jù)(一般為512或1k)來訪問設(shè)備。塊設(shè)備通過buffer cache(內(nèi)存緩沖區(qū))訪問,可以隨機(jī)存取,即:任何塊都可以讀寫,不必考慮它在設(shè)備的什么地方。塊設(shè)備可以通過它們的設(shè)備特殊文件訪問,但是更常見的是通過文件系統(tǒng)進(jìn)行訪問。只有一個塊設(shè)備可以支持一個安裝的文件系統(tǒng)。比如我們常見的電腦硬盤、SD卡、U盤、光盤等,就像女人一樣是用來存儲信息的。3) 網(wǎng)絡(luò)接口:任何網(wǎng)絡(luò)事務(wù)都經(jīng)過一個網(wǎng)絡(luò)接口形成,即一個能夠和其他主機(jī)交換數(shù)據(jù)的設(shè)備。訪問網(wǎng)絡(luò)接口的方法仍然是給它們分配一個唯一的名字(比如eth0),但這個名字在文件系統(tǒng)中不存在對應(yīng)的節(jié)點(diǎn)。內(nèi)核和網(wǎng)絡(luò)設(shè)備驅(qū)動程序間的通信,完全不同于內(nèi)核和字符以及塊驅(qū)動程序之間的通信,內(nèi)核調(diào)用一套和數(shù)據(jù)包傳輸相關(guān)的函數(shù)(socket函數(shù))而不是read、write等。比如我們常見的網(wǎng)卡設(shè)備、藍(lán)牙設(shè)備,就像女博士一樣,數(shù)量稀少但又不可或缺。linux中所有的驅(qū)動程序最終都能歸到這三種設(shè)備中,當(dāng)然他們之間也沒有非常嚴(yán)格的界限,這些都是程序中對他們的劃分而已,比如一個sd卡,我們也可以把它封裝成字符設(shè)備去操作也是沒有問題的。就像三、設(shè)備文件、主設(shè)備號、從設(shè)備號有了設(shè)備類型的劃分,那么應(yīng)用程序應(yīng)該怎樣訪問具體的硬件設(shè)備呢?或者說已經(jīng)確定他是一個男人了,那么怎么從萬千世界中區(qū)分他與他的不同呢?答案是:姓名,在linux驅(qū)動中也就是設(shè)備文件名。那么重名怎么辦?答案是:身份證號,在linux驅(qū)動中也就是設(shè)備號(主、從)。設(shè)備文件:在linux 系統(tǒng) 中有一個約定俗成的說法:“一切皆文件”, 應(yīng)用程序使用設(shè)備文件節(jié)點(diǎn)訪問對應(yīng)設(shè)備, Linux下的各種硬件設(shè)備以文件的形式存放于/dev目錄下,可以使用ls /dev 查看 Linux把對硬件的操作全部抽象成對文件的操作 (open,read,write,close,)每個設(shè)備文件都有其文件屬性(c或者b),使用ls /dev -l 的命令查看, 表明其是字符設(shè)備或者塊設(shè)備,網(wǎng)絡(luò)設(shè)備沒有在這個文件夾下,用來明其性別(男人、女人)主設(shè)備號、從設(shè)備號在設(shè)備管理中,除了設(shè)備類型外,內(nèi)核還需要一對被稱為主從設(shè)備號的參數(shù),才能唯一標(biāo)識一個設(shè)備,類似人的身份證號主設(shè)備號:用于標(biāo)識驅(qū)動程序,相同的主設(shè)備號使用相同的驅(qū)動程序,例如:S3C2440 有串口、LCD、觸摸屏三種設(shè)備,他們的主設(shè)備號各不相同;從設(shè)備號:用于標(biāo)識同一驅(qū)動程序的不同硬件例:PC的IDE設(shè)備,主設(shè)備號用于標(biāo)識該硬盤,從設(shè)備號用于標(biāo)識每個分區(qū),2440有三個串口,每個串口的主設(shè)備號相同,從設(shè)備號用于區(qū)分具體屬于那一個串口。四、驅(qū)動程序與應(yīng)用程序的區(qū)別應(yīng)用程序以main開始驅(qū)動程序沒有main,它以一個模塊初始化函數(shù)作為入口應(yīng)用程序從頭到尾執(zhí)行一個任務(wù)驅(qū)動程序完成初始化之后不再運(yùn)行,等待系統(tǒng)調(diào)用應(yīng)用程序可以使用glibc等標(biāo)準(zhǔn)C函數(shù)庫驅(qū)動程序不能使用標(biāo)準(zhǔn)C庫五、用戶態(tài)與內(nèi)核態(tài)的區(qū)分驅(qū)動程序是內(nèi)核的一部分,工作在內(nèi)核態(tài)應(yīng)用程序工作在用戶態(tài)數(shù)據(jù)空間訪問問題無法通過指針直接將二者的數(shù)據(jù)地址進(jìn)行傳遞系統(tǒng)提供一系列函數(shù)幫助完成數(shù)據(jù)空間轉(zhuǎn)換get_userput_usercopy_from_usercopy_to_user六、Linux驅(qū)動程序功能對設(shè)備初始化和釋放資源把數(shù)據(jù)從內(nèi)核傳送到硬件和從硬件讀取數(shù)據(jù)讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)和回送應(yīng)用程序請求的數(shù)據(jù)檢測和處理設(shè)備出現(xiàn)的錯誤(底層協(xié)議)用于區(qū)分具體設(shè)備的實(shí)例三:linux驅(qū)動基礎(chǔ)開發(fā)2linux 驅(qū)動開發(fā)前奏(模塊編程)一、linux內(nèi)核模塊簡介linux內(nèi)核整體結(jié)構(gòu)非常龐大,其包含的組件也非常多。我們怎么把需要的部分都包含在內(nèi)核中呢?一種辦法是把所有的需要的功能都編譯到內(nèi)核中。這會導(dǎo)致兩個問題,一是生成的內(nèi)核會很大,二是如果我們要在現(xiàn)有的內(nèi)核中新增或刪除功能,不得不重新編譯內(nèi)核,工作效率會非常的低,同時如果編譯的模塊不是很完善,很有可能會造成內(nèi)核崩潰。linux提供了另一種機(jī)制來解決這個問題,這種集中被稱為模塊,可以實(shí)現(xiàn)編譯出的內(nèi)核本身并不含有所有功能,而在這些功能需要被使用的時候,其對應(yīng)的代碼可以被動態(tài)的加載到內(nèi)核中。二、模塊特點(diǎn):1)模塊本身并不被編譯入內(nèi)核,從而控制了內(nèi)核的大小。2)模塊一旦被加載,他就和內(nèi)核中的其他部分完全一樣。注意:模塊并不是驅(qū)動的必要形式:即:驅(qū)動不一定必須是模塊,有些驅(qū)動是直接編譯進(jìn)內(nèi)核的;同時模塊也不全是驅(qū)動,例如我們寫的一些很小的算法可以作為模塊編譯進(jìn)內(nèi)核,但它并不是驅(qū)動。就像燒餅不一定是圓的,圓的也不都是燒餅一樣。三、最簡單的模塊分析1)以下是一個最簡單的模塊例子1. #include/*printk()*/2. #include/*_init_exit*/3. 4. staticint_inithello_init(void)/*模塊加載函數(shù),通過insmod命令加載模塊時,被自動執(zhí)行*/5. 6. printk(KERN_INFOHelloWorldentern);7. return0;8. 9. staticvoid_exithello_exit(void)/*模塊卸載函數(shù),當(dāng)通過rmmod命令卸載時,會被自動執(zhí)行*/10. 11. printk(KERN_INFOHelloWorldexitn);12. 13. 14. module_init(hello_init);15. module_exit(hello_exit);16. 17. MODULE_AUTHOR(dengwei);/*模塊作者,可選*/18. MODULE_LICENSE(DualBSD/GPL);/*模塊許可證明,描述內(nèi)核模塊的許可權(quán)限,必須*/19. 20. MODULE_DESCRIPTION(AsimpleHelloWorldModule);/*模塊說明,可選*/21. MODULE_ALIAS(asimplestmodule);/*模塊說明,可選*/22. 2) 以下是編譯上述模塊所需的編寫的makefile1. obj-m:=hello.o/目標(biāo)文件2. #module-objs:=file.o/當(dāng)模塊有多個文件組成時,添加本句3. KDIR:=/usr/src/linux/內(nèi)核路徑,根據(jù)實(shí)際情況換成自己的內(nèi)核路徑,嵌入式的換成嵌入式,PC機(jī)的指定PC機(jī)路徑4. PWD:=$(shellpwd)/模塊源文件路徑5. all:6. $(MAKE)-C$(KDIR)SUBDIRS=$(PWD)modules7. rm-rf*.mod.*8. rm-rf.*.cmd9. rm-rf*.o10. rm-rfModule.*11. clean:12. rm-rf*.ko最終會編譯得到:hello.ko文件使用insmodhello.ko將模塊插入內(nèi)核,然后使用dmesg即可看到輸出提示信息。常用的幾種模塊操作:insmod XXX.ko 加載指定模塊lsmod 列舉當(dāng)前系統(tǒng)中的所有模塊rmmod XXX 卸載指定模塊(注意沒有。ko后綴)dmesg 當(dāng)打印等級低于默認(rèn)輸出等級時,采用此命令查看系統(tǒng)日志3)linux內(nèi)核模塊的程序結(jié)構(gòu)1.模塊加載函數(shù):Linux內(nèi)核模塊一般以_init標(biāo)示聲明,典型的模塊加載函數(shù)的形式如下:1. staticint_initmyModule_init(void)2. 3. /*Moduleinitcode*/4. PRINTK(myModule_initn);5. return0;6. 7. module_init(myModule_init);模塊加載函數(shù)的名字可以隨便取,但必須以“module_init(函數(shù)名)”的形式被指定;執(zhí)行insmod命令時被執(zhí)行,用于初始化模塊所必需資源,比如內(nèi)存空間、硬件設(shè)備等;它返回整形值,若初始化成功,應(yīng)返回0,初始化失敗返回負(fù)數(shù)。2.模塊卸載函數(shù)典型的模塊卸載函數(shù)形式如下:1. staticvoid_exitmyModule_exit(void)2. 3. /*Moduleexitcode*/4. PRINTK(myModule_exitn);5. return;6. 7. module_exit(myModule_exit);模塊卸載函數(shù)在模塊卸載的時候執(zhí)行,不返回任何值,需用“module_exit(函數(shù)名)”的形式被指定。卸載模塊完成與加載函數(shù)相反的功能:若加載函數(shù)注冊了XXX,則卸載函數(shù)應(yīng)當(dāng)注銷XXX若加載函數(shù)申請了內(nèi)存空間,則卸載函數(shù)應(yīng)當(dāng)釋放相應(yīng)的內(nèi)存空間若加載函數(shù)申請了某些硬件資源(中斷、DMA、I/0端口、I/O內(nèi)存等),則卸載函數(shù)應(yīng)當(dāng)釋放相應(yīng)的硬件資源若加載函數(shù)開啟了硬件,則卸載函數(shù)應(yīng)當(dāng)關(guān)閉硬件。其中_init 、_exit 為系統(tǒng)提供的兩種宏,表示其所修飾的函數(shù)在調(diào)用完成后會自動回收內(nèi)存,即內(nèi)核認(rèn)為這種函數(shù)只會被執(zhí)行1次,然后他所占用的資源就會被釋放。3.模塊聲明與描述在linux內(nèi)核模塊中,我們可以用MODULE_AUTHOR、MODULE_DESCRIPTION、MODULE_VERSION、MODULE_TABLE、MODULE_ALIA,分別描述模塊的作者、描述、版本、設(shè)備表號、別名等。1. MODULE_AUTHOR(dengwei);2. MODULE_LICENSE(DualBSD/GPL);3. MODULE_DESCRIPTION(AsimpleHelloWorldModule);4. MODULE_ALIAS(asimplestmodule);四、有關(guān)模塊的其它特性1)模塊參數(shù):我們可以利用module_param(參數(shù)名、參數(shù)類型、參數(shù)讀寫屬性) 為模塊定義一個參數(shù),例如:1. staticchar*string_test=“thisisatest”;2. staticnum_test=1000;3. module_param(num_test,int,S_IRUGO);4. module_param(steing_test,charp,S_ITUGO);在裝載模塊時,用戶可以給模塊傳遞參數(shù),形式為:“insmod 模塊名 參數(shù)名=參數(shù)值”,如果不傳遞,則參數(shù)使用默認(rèn)的參數(shù)值參數(shù)的類型可以是:byte,short,ushort,int,uint,long,ulong,charp,bool;權(quán)限:定義在linux/stat.h中,控制存取權(quán)限,S_IRUGO表示所有用戶只讀;模塊被加載后,在sys/module/下會出現(xiàn)以此模塊命名的目錄,當(dāng)讀寫權(quán)限為零時:表示此參數(shù)不存在sysfs文件系統(tǒng)下的文件節(jié)點(diǎn),當(dāng)讀寫權(quán)限不為零時:此模塊的目錄下會存在parameters目錄,包含一系列以參數(shù)名命名的文件節(jié)點(diǎn),這些文件節(jié)點(diǎn)的權(quán)限值就是傳入module_param()的“參數(shù)讀/寫權(quán)限”,而該文件的內(nèi)容為參數(shù)的值。除此之外,模塊也可以擁有參數(shù)數(shù)組,形式為:“module_param_array(數(shù)組名、數(shù)組類型、數(shù)組長、參數(shù)讀寫權(quán)限等)”,當(dāng)不需要保存實(shí)際的輸入的數(shù)組元素的個數(shù)時,可以設(shè)置“數(shù)組長”為0。運(yùn)行insmod時,使用逗號分隔輸入的數(shù)組元素。下面是一個實(shí)際的例子,來說明模塊傳參的過程。1. #include/*module_init()*/2. #include/*printk()*/3. #include/*_init_exit*/4. 5. #defineDEBUG/opendebugmessage6. 7. #ifdefDEBUG8. #definePRINTK(fmt,arg.)printk(KERN_WARNINGfmt,#arg)9. #else10. #definePRINTK(fmt,arg.)printk(KERN_DEBUGfmt,#arg)11. #endif12. 13. staticchar*string_test=defaultparamater;14. staticintnum_test=1000;15. 16. staticint_inithello_init(void)17. 18. PRINTK(nthestring_testis:%sn,string_test);19. PRINTK(thenum_testis:%dn,num_test);20. return0;21. 22. 23. staticvoid_exithello_exit(void)24. 25. PRINTK(inputparamatermoduleexitn);26. 27. 28. module_init(hello_init);29. module_exit(hello_exit);30. 31. module_param(num_test,int,S_IRUGO);32. module_param(string_test,charp,S_IRUGO);33. 34. MODULE_AUTHOR(dengwei);35. MODULE_LICENSE(GPL);當(dāng)執(zhí)行 insmod hello_param.ko時,執(zhí)行dmesg 查看內(nèi)核輸出信息:1. HelloWorldenter2. theteststringis:thisisatest3. thetestnumis:1000當(dāng)執(zhí)行insmod hello_param.ko num_test=2000 string_test=“edit by dengwei”,執(zhí)行dmesg查看內(nèi)核輸出信息:1. HelloWorldenter2. theteststringis:editbydengwei3. thetestnumis:20002)導(dǎo)出模塊及符號的相互引用Linux2.6內(nèi)核的“/proc/kallsyms”文件對應(yīng)內(nèi)核符號表,它記錄了符號以及符號所在的內(nèi)存地址,模塊可以使用下列宏導(dǎo)到內(nèi)核符號表中。EXPORT_SYMBOL(符號名); 任意模塊均可EXPORT_SYMBOL_GPL(符號名); 只使用于包含GPL許可權(quán)的模塊導(dǎo)出的符號可以被其它模塊使用,使用前聲明一下即可。下面給出一個簡單的例子:將add sub符號導(dǎo)出到內(nèi)核符號表中,這樣其它的模塊就可以利用其中的函數(shù)1. #include/*module_init()*/2. #include/*printk()*/3. #include/*_init_exit*/4. 5. intadd_test(inta,intb)6. 7. returna+b;8. 9. 10. intsub_test(inta,intb)11. 12. returna-b;13. 14. 15. EXPORT_SYMBOL(add_test);16. EXPORT_SYMBOL(sub_test);17. 18. MODULE_AUTHOR(dengwei);19. MODULE_LICENSE(GPL);執(zhí)行 cat/proc/kallsyms | grep test 即可找到以下信息,表示模塊確實(shí)被加載到內(nèi)核表中。1. f88c9008r_ksymtab_sub_integarexport_symb2. f88c9020r_kstrtab_sub_integarexport_symb3. f88c9018r_kcrctab_sub_integarexport_symb4. f88c9010r_ksymtab_add_integarexport_symb5. f88c902cr_kstrtab_add_integarexport_symb6. f88c901cr_kcrctab_add_integarexport_symb7. f88c9000Tadd_tesexport_symb8. f88c9004Tsub_tesexport_symb9. 13db98c9a_crc_sub_integarexport_symb10. e1626deea_crc_add_integarexport_symb在其它模塊中可以引用此符號1. #include/*module_init()*/2. #include/*printk()*/3. #include/*_init_exit*/4. 5. #defineDEBUG/opendebugmessage6. 7. #ifdefDEBUG8. #definePRINTK(fmt,arg.)printk(KERN_WARNINGfmt,#arg)9. #else10. #definePRINTK(fmt,arg.)printk(KERN_DEBUGfmt,#arg)11. #endif12. 13. externintadd_test(inta,intb);14. externintsub_test(inta,intb);15. 16. staticint_inithello_init(void)17. 18. inta,b;19. 20. a=add_test(10,20);21. b=sub_test(30,20);22. PRINTK(theaddtestresultis%d,a);23. PRINTK(thesubtestresultis%dn,b);24. return0;25. 26. 27. staticvoid_exithello_exit(void)28. 29. PRINTK(HelloWorldexitn);30. 31. 32. module_init(hello_init);33. module_exit(hello_exit);34. 35. MODULE_AUTHOR(dengwei);36. MODULE_LICENSE(GPL);四:linux驅(qū)動基礎(chǔ)開發(fā)3linux 內(nèi)核配置機(jī)制(make menuconfig、Kconfig、makefile)講解前面我們介紹模塊編程的時候介紹了驅(qū)動進(jìn)入內(nèi)核有兩種方式:模塊和直接編譯進(jìn)內(nèi)核,并介紹了模塊的一種編譯方式在一個獨(dú)立的文件夾通過makefile配合內(nèi)核源碼路徑完成。那么如何將驅(qū)動直接編譯進(jìn)內(nèi)核呢?在我們實(shí)際內(nèi)核的移植配置過程中經(jīng)常聽說的內(nèi)核裁剪又是怎么麼回事呢?我們在進(jìn)行l(wèi)inux內(nèi)核配置的時候經(jīng)常會執(zhí)行make menuconfig這個命令,然后屏幕上會出現(xiàn)以下界面:這個界面是怎么生成的呢?跟我們經(jīng)常說的內(nèi)核配置與與編譯又有什么關(guān)系呢?下面我們借此來講解一下linux內(nèi)核的配置機(jī)制及其編譯過程。一、配置系統(tǒng)的基本結(jié)構(gòu)Linux內(nèi)核的配置系統(tǒng)由三個部分組成,分別是:1、Makefile:分布在 Linux 內(nèi)核源代碼根目錄及各層目錄中,定義 Linux 內(nèi)核的編譯規(guī)則;2、配置文件(config.in(2.4內(nèi)核,2.6內(nèi)核):給用戶提供配置選擇的功能;3、配置工具:包括配置命令解釋器(對配置腳本中使用的配置命令進(jìn)行解釋)和配置用戶界面(提供基于字符界面、基于 Ncurses 圖形界面以及基于 Xwindows 圖形界面的用戶配置界面,各自對應(yīng)于 Make config、Make menuconfig 和 make xconfig)。這些配置工具都是使用腳本語言,如 Tcl/TK、Perl 編寫的(也包含一些用 C 編寫的代碼)。本文并不是對配置系統(tǒng)本身進(jìn)行分析,而是介紹如何使用配置系統(tǒng)。所以,除非是配置系統(tǒng)的維護(hù)者,一般的內(nèi)核開發(fā)者無須了解它們的原理,只需要知道如何編寫 Makefile 和配置文件就可以。二、make過程講解當(dāng)我們在執(zhí)行make menuconfig這個命令時,系統(tǒng)到底幫我們做了哪些工作呢?這里面一共涉及到了一下幾個文件我們來一一講解Linux內(nèi)核根目錄下的scripts文件夾arch/$ARCH/Kconfig文件、各層目錄下的Kconfig文件Linux內(nèi)核根目錄下的makefile文件、各層目錄下的makefile文件Linux內(nèi)核根目錄下的的。config文件、arm/$ARCH/下的config文件Linux內(nèi)核根目錄下的 include/generated/autoconf.h文件1)scripts文件夾存放的是跟make menuconfig配置界面的圖形繪制相關(guān)的文件,我們作為使用者無需關(guān)心這個文件夾的內(nèi)容2)當(dāng)我們執(zhí)行make menuconfig命令出現(xiàn)上述藍(lán)色配置界面以前,系統(tǒng)幫我們做了以下工作:首先系統(tǒng)會讀取arch/$ARCH/目錄下的Kconfig文件生成整個配置界面選項(Kconfig是整個linux配置機(jī)制的核心),那么ARCH環(huán)境變量的值等于多少呢?它是由linux內(nèi)核根目錄下的makefile文件決定的,在makefile下有此環(huán)境變量的定義:或者通過 make ARCH=arm menuconfig命令來生成配置界面,默認(rèn)生成的界面是所有參數(shù)都是沒有值的比如教務(wù)處進(jìn)行考試,考試科數(shù)可能有外語、語文、數(shù)學(xué)等科,這里相當(dāng)于我們選擇了arm科可進(jìn)行考試,系統(tǒng)就會讀取arm/arm/kconfig文件生成配置選項(選擇了arm科的卷子),系統(tǒng)還提供了x86科、milps科等10幾門功課的考試題4) 假設(shè)教務(wù)處比較“仁慈”,為了怕某些同學(xué)做不錯試題,還給我們準(zhǔn)備了一份參考答案(默認(rèn)配置選項),存放在arch/$ARCH/configs下,對于arm科來說就是arch/arm/configs文件夾:5)此文件夾中有許多選項,系統(tǒng)會讀取哪個呢?內(nèi)核默認(rèn)會讀取linux內(nèi)核根目錄下。config文件作為內(nèi)核的默認(rèn)選項(試題的參考答案),我們一般會根據(jù)開發(fā)板的類型從中選取一個與我們開發(fā)板最接近的系列到Linux內(nèi)核根目錄下(選擇一個最接近的參考答案)#cp arch/arm/configs/s3c2410_defconfig .config4)config假設(shè)教務(wù)處留了一個心眼,他提供的參考答案并不完全正確(。config文件與我們的板子并不是完全匹配),這時我們可以選擇直接修改。config文件然后執(zhí)行make menuconfig命令讀取新的選項但是一般我們不采取這個方案,我們選擇在配置界面中通過空格、esc、回車選擇某些選項選中或者不選中,最后保存退出的時候,Linux內(nèi)核會把新的選項(正確的參考答案)更新到。config中,此時我們可以把。config重命名為其它文件保存起來(當(dāng)你執(zhí)行make distclean時系統(tǒng)會把。config文件刪除),以后我們再配置內(nèi)核時就不需要再去arch/arm/configs下考取相應(yīng)的文件了,省去了重新配置的麻煩,直接將保存的。config文件復(fù)制為。config即可。5)經(jīng)過以上兩步,我們可以正確的讀取、配置我們需要的界面了那么他們?nèi)绾胃鷐akefile文件建立編譯關(guān)系呢?當(dāng)你保存make menuconfig選項時,系統(tǒng)會除了會自動更新。config外,還會將所有的選項以宏的形式保存在Linux內(nèi)核根目錄下的 include/generated/autoconf.h文件下內(nèi)核中的源代碼就都會包含以上。h文件,跟宏的定義情況進(jìn)行條件編譯。當(dāng)我們需要對一個文件整體選擇如是否編譯時,還需要修改對
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 大學(xué)化學(xué)考試實(shí)驗步驟試題及答案
- 聽覺訓(xùn)練的重要性與方法探討試題及答案
- 優(yōu)化商務(wù)會議表達(dá)的試題及答案
- 新能源汽車行業(yè)的未來技術(shù)趨勢試題及答案
- 衛(wèi)生中級考試試題及答案
- 農(nóng)業(yè)電商產(chǎn)品線規(guī)劃策略試題及答案
- 如何完善創(chuàng)業(yè)扶持政策的評估體系試題及答案
- 電動汽車的國際市場研究試題及答案
- 注冊土木工程師學(xué)習(xí)小技巧分享試題及答案
- 安全工程師實(shí)務(wù)考試考核2025年試題及答案
- 2025專利代理師筆試考試題庫有答案分析
- 中考語文課內(nèi)文言文閱讀專題復(fù)習(xí)練習(xí)
- 危重癥患者體位管理
- 湖南省名校聯(lián)考聯(lián)合體2024-2025學(xué)年高一下學(xué)期期中考試地理試題 含答案
- 2025春粵教粵科版(2024)小學(xué)科學(xué)一年級下冊(全冊)教案、教學(xué)反思、教學(xué)計劃(附教材目錄P103)
- 2025年陜西高中學(xué)業(yè)水平合格考數(shù)學(xué)試卷及答案
- 2025年天津市紅橋區(qū)中考第一次模擬考試物理試卷(含答案)
- 2025河北省國內(nèi)旅游組團(tuán)合同示范文本
- 水利水電工程基建資料
- 客情維護(hù)培訓(xùn)
- 煤炭行業(yè)“技能大師”工作室入圍復(fù)評-答辯
評論
0/150
提交評論