嵌入式Linux系統(tǒng)的搭建與配置過程_第1頁(yè)
嵌入式Linux系統(tǒng)的搭建與配置過程_第2頁(yè)
嵌入式Linux系統(tǒng)的搭建與配置過程_第3頁(yè)
嵌入式Linux系統(tǒng)的搭建與配置過程_第4頁(yè)
嵌入式Linux系統(tǒng)的搭建與配置過程_第5頁(yè)
已閱讀5頁(yè),還剩9頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、目錄1 .摘要22 .UBOOT,LINUX內(nèi)核,文件系統(tǒng)的介紹及相互關(guān)系.32.1 嵌入式系統(tǒng)簡(jiǎn)介32.2 嵌入式Linux概述32.3 UBOOT簡(jiǎn)介.43 .UBOOT的啟動(dòng)過程.64 .內(nèi)核的主要功能和裁剪74.1 Linux的編譯74.2 嵌入式Linux的配置和剪裁.85 .文件系統(tǒng)的制作過程86 .交叉編譯器的搭建和環(huán)境變量的設(shè)置.97 .驅(qū)動(dòng)程序的編寫過程與關(guān)鍵點(diǎn)117.1 Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序的結(jié)構(gòu)117.2 網(wǎng)絡(luò)驅(qū)動(dòng)程序的基本方法127.3 網(wǎng)絡(luò)驅(qū)動(dòng)程序中用到的數(shù)據(jù)結(jié)構(gòu).127.4 常用的系統(tǒng)支持.147.5 編寫Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序中需要注意的問題188 .參考文獻(xiàn).

2、20摘要嵌入式系統(tǒng)是以應(yīng)用為中心,以計(jì)算機(jī)為基礎(chǔ),并且軟硬件可裁剪,適用于應(yīng)用系統(tǒng)對(duì)功能、可靠性、成本、體積、功耗有嚴(yán)格要求的專用計(jì)算機(jī)系統(tǒng)。嵌入式系統(tǒng)一般由嵌入式微處理器、外圍硬件設(shè)備、嵌入式操作系統(tǒng)以及用戶的應(yīng)用程序4部分組成,用于實(shí)現(xiàn)對(duì)其它設(shè)備的控制、監(jiān)視或管理等功能。其廣泛應(yīng)用于控制領(lǐng)域、消費(fèi)電子產(chǎn)品等行業(yè),已成為現(xiàn)代電子領(lǐng)域的重要研究方向之一。嵌入式Linux的研究已經(jīng)成為當(dāng)前信息技術(shù)研究的熱點(diǎn),它的應(yīng)用蘊(yùn)含著巨大的商業(yè)價(jià)值,并且己經(jīng)廣泛的應(yīng)用于各種信息家電、通訊產(chǎn)品、工業(yè)控制中。論文首先介紹了ARM和嵌入式Linux操作系統(tǒng)的特點(diǎn)和當(dāng)前的發(fā)展概況。然后闡述了嵌入式Linux開發(fā)流程

3、以及移植到具體硬件平臺(tái)需要完成的工作,如U-Boot的移植、Linux內(nèi)核的編譯與裁剪、文件系統(tǒng)的制作、驅(qū)動(dòng)程序的編寫等。關(guān)鍵字:嵌入式;ARM;嵌入式Linux;Linux內(nèi)核;驅(qū)動(dòng)程序2. LINUX,UBOOT,文件系統(tǒng)的介紹及相互關(guān)系2.1 嵌入式系統(tǒng)簡(jiǎn)介嵌入式系統(tǒng)是以應(yīng)用為中心,以計(jì)算機(jī)為基礎(chǔ),并且軟硬件可裁剪,適用于應(yīng)用系統(tǒng)對(duì)功能、可靠性、成本、體積、功耗有嚴(yán)格要求的專用計(jì)算機(jī)系統(tǒng)。單片機(jī)、單板機(jī)控制系統(tǒng)以及一些專用的工業(yè)控制計(jì)算機(jī)都可以稱作嵌入式系統(tǒng),它是嵌入式系統(tǒng)領(lǐng)域的重要組成部分,只是更著重于對(duì)各自硬件系統(tǒng)的研究。嵌入式系統(tǒng)更著重于對(duì)軟件系統(tǒng)進(jìn)行研究,順應(yīng)了軟硬件協(xié)同設(shè)計(jì)以及

4、應(yīng)用需求的發(fā)展。目前,嵌入式系統(tǒng)己逐步發(fā)展成為一門學(xué)科,朝著系統(tǒng)化和規(guī)范化的方面發(fā)展。嵌入式系統(tǒng)學(xué)科和產(chǎn)業(yè)的發(fā)展使得設(shè)計(jì)人員能夠從容地面對(duì)越來越復(fù)雜的應(yīng)用需求,通過軟件和硬件的模塊化設(shè)計(jì)大大地簡(jiǎn)化和加快應(yīng)用系統(tǒng)的開發(fā).嵌入式系統(tǒng)主要包括硬件和軟件兩部分。硬件包括處理器、存儲(chǔ)器及外部設(shè)備、I0端口和圖形控制器等;軟件部分包寸S操作系統(tǒng)(OS)和用戶應(yīng)用程序。嵌入式系統(tǒng)硬件的核心是嵌入式微處理器。它的功能、外設(shè)集成度、速度、功耗、體積、成本、可靠性和電磁兼容性等方面均受到應(yīng)用要求的制約,是各個(gè)半導(dǎo)體廠商之間競(jìng)爭(zhēng)的熱點(diǎn)。嵌入式系統(tǒng)的軟件是實(shí)現(xiàn)嵌入式系統(tǒng)功能的關(guān)鍵,軟件要求固化存儲(chǔ),代碼的高質(zhì)量、高可

5、靠性和高實(shí)時(shí)性在許多場(chǎng)合也是基本要求。多任務(wù)嵌入式操作系統(tǒng)是知識(shí)集成的平臺(tái),是嵌入式系統(tǒng)走向工業(yè)標(biāo)準(zhǔn)化道路的基礎(chǔ),是嵌入式系統(tǒng)研究的重要方向?,F(xiàn)在人們講嵌入式系統(tǒng)時(shí),某種程度上是指近些年來比較熱門的具有操作系統(tǒng)的嵌入式系統(tǒng)。2.2 嵌入式Linux概述Linux操作系統(tǒng)源于芬蘭一位大學(xué)生LinusTorvalds的課余作品,隨著Intemet的發(fā)展,Linux操作系統(tǒng)在全球計(jì)算機(jī)愛好者的關(guān)懷下,不斷地發(fā)展和成長(zhǎng),己成為當(dāng)前最流行的免費(fèi)操作系統(tǒng),任何人都可以自由的使用Linux源程序。嵌入式Linux操作系統(tǒng)的組成,我們可以和PC機(jī)相對(duì)應(yīng)來理解,在PC機(jī)上,Windows的啟動(dòng)大致有BIOS、內(nèi)

6、核、文件系統(tǒng)和初始化程序幾個(gè)部分;那么相對(duì)而言,嵌入式Linux的移植有Bootloader、Linux內(nèi)核、文件系統(tǒng)、初始化和用戶的應(yīng)用程序幾部分,Bootloader完成系統(tǒng)的初始化和引導(dǎo)。Linux操作系統(tǒng)具有以下幾大特點(diǎn):(1)開放源碼,豐富的軟件資源Linux遵循GPL(GNU通用許可證),用法律保障了用戶免費(fèi)獲得內(nèi)核源代碼的權(quán)利。由于嵌入式系統(tǒng)千差萬(wàn)別,往往需要針對(duì)某一具體應(yīng)用去修改和優(yōu)化系統(tǒng),這樣,能否獲得源代碼就至關(guān)重要。Linux是自由的操作系統(tǒng),它的開放源代碼使用戶獲得了最大的自由度。Linux上的軟件資源十分豐富,每種通用程序在Linux上都可以找到,并且每天都在增加。在

7、Linux上往往不需要從頭做起,而是先選擇一個(gè)類似的自由軟件,進(jìn)行二次開發(fā)。這就大大節(jié)省了開發(fā)工作量,縮短了開發(fā)時(shí)間。(2)功能強(qiáng)大的內(nèi)核,性能高效、穩(wěn)定、多任務(wù)Linux的內(nèi)核非常穩(wěn)定。它的高效和穩(wěn)定性已經(jīng)在各個(gè)領(lǐng)域,尤其在網(wǎng)絡(luò)服務(wù)器領(lǐng)域得到了事實(shí)的驗(yàn)證,而且Linux內(nèi)核小巧靈活,易于裁剪。這使Linux能很適合嵌入式系統(tǒng)的應(yīng)用。(3)支持多種體系結(jié)構(gòu)Linux能支持X86,ARM,MIPS,POWERP,ALPHA,SPARC等多種體系結(jié)構(gòu)。目前,Linux己被移植到數(shù)十種硬件平臺(tái)上,幾乎所有流行的CPU,Linux都支持。(4)完善的網(wǎng)絡(luò)通信、圖形和文件管理機(jī)制Linux自產(chǎn)生之日起就

8、與網(wǎng)絡(luò)密不可分,網(wǎng)絡(luò)是Linux的強(qiáng)項(xiàng)。另外,它支持ext2,fatl6,fat32,romfs等多種文件操作系統(tǒng)。在圖形系統(tǒng)方面,Linux上既有成熟的xWindow,也有embedcdQT,MiniGUI等嵌入式圖形用戶界面GUI,還有ysvgalib,framebuffer等優(yōu)秀工具,可以適合不同的用途。(5)支持大量的周邊硬件設(shè)備,驅(qū)動(dòng)豐富Linux上的驅(qū)動(dòng)己經(jīng)非常豐富了,支持各種主流硬件設(shè)備和最新硬件技術(shù),而且隨著Linux的廣泛應(yīng)用,許多芯片廠家也已經(jīng)開始提供Linux上的驅(qū)動(dòng)。這一步促進(jìn)了Linux各種硬件平臺(tái)上的應(yīng)用。(6)大小功能都可定制Linux繼承了Unix的優(yōu)秀設(shè)計(jì)思想

9、,內(nèi)核與用戶界面是完全獨(dú)立的。它非常靈活,各部分的可定制性都很強(qiáng),能適合多種需求。2.3 UBOOT簡(jiǎn)介UBoot是一個(gè)非常復(fù)雜的東酉,它也體現(xiàn)了嵌入式系統(tǒng)的一個(gè)非常重要的特征:自己定制。它脫胎于PC機(jī)的Linux,可從網(wǎng)站上直接下載,U.Boot和其它任何BOOTLOADER都是一樣的,主要實(shí)現(xiàn)對(duì)系統(tǒng)進(jìn)行初始化、系統(tǒng)引導(dǎo)、FLASH操作等功能。開發(fā)平臺(tái)的UBoot主要是對(duì)板子的硬件進(jìn)行初始化,包括:時(shí)鐘和PLL、定時(shí)器、調(diào)試用D(DebugDART)等等。有了U.B00t我們可以在主機(jī)的超級(jí)終端通過調(diào)試串口和目標(biāo)機(jī)進(jìn)行通信和設(shè)置。2.3.1 編譯U-Boot在Linux系統(tǒng)下,用下面的命令對(duì)

10、UBoot進(jìn)行編譯$cdUBOOT;進(jìn)入目錄Smakeat91rm9200dk_eonfig編譯Smakeall$gzip_cu-boot.bin>u-boot.gz;壓縮為gz文件編譯bootbin$cdBootSmake編譯loaderbin$cdLoaderSmake2.3.2 U.Boot命令在本系統(tǒng)中,采用的是U-Boot,U-Boot在嵌入式系統(tǒng)中相當(dāng)于Pc機(jī)的BIOS加上操作系統(tǒng)引導(dǎo)頭部的內(nèi)容,并且引導(dǎo)操作系統(tǒng)進(jìn)行裝載和運(yùn)行,UBoot啟動(dòng)后有一系列的命令,使得我們能夠方便的對(duì)FLASH、RAM進(jìn)行操作,UBoot已經(jīng)對(duì)系統(tǒng)的頻率、定時(shí)器進(jìn)行了設(shè)置,初始化了一個(gè)調(diào)試串口,我

11、們可以通過串口或者以太網(wǎng)進(jìn)行數(shù)據(jù)的下載。下面是UBoot常用的命令:go一在地址addr'處開始程序執(zhí)行run一運(yùn)行命令bootm一從內(nèi)存中進(jìn)行應(yīng)用程序影像運(yùn)行bootp一通過網(wǎng)絡(luò)用BootPTFTP協(xié)議來啟動(dòng)影像tf砸boot一通過網(wǎng)絡(luò)用TFTP協(xié)議、設(shè)置服務(wù)器和客戶機(jī)的IP地址進(jìn)行影像文件傳送loadb-通過用口線(kermitmode)來裝載二進(jìn)制文件pfintcnv一打印環(huán)境變量setcnv一設(shè)置環(huán)境變量saveenv一保存環(huán)境變量到內(nèi)存下面是UBoot的簡(jiǎn)單環(huán)境變量baudrate一波特率bootdelay-Boot延遲bootcmd-Boot命令bootargsBoot參數(shù)

12、ipaddr一客戶機(jī)IP地址servefip一服務(wù)器地址loadaddr一裝載地址etlladdr一網(wǎng)卡MAC地址3.UBOOT的啟動(dòng)過程嵌入式Linux系統(tǒng)一般沒有自舉程序,必須通過啟動(dòng)程序來引導(dǎo)硬件系統(tǒng)進(jìn)入操作系統(tǒng)。啟動(dòng)程序的工作包括:改變系統(tǒng)時(shí)鐘、關(guān)閉WATCHDOG始化存儲(chǔ)控制器等。本文針對(duì)本嵌入式控制系統(tǒng)所需的硬件方案,植入U(xiǎn)boot1-3.4啟動(dòng)程序。U-Boot是一種功能強(qiáng)大的引導(dǎo)轉(zhuǎn)載程序。它不僅支持Linux、Vxworks等操作系統(tǒng),還支持PowerPCARM?多種系列處理器。Uboot啟動(dòng)過程分為兩個(gè)階段。第一階段由匯編來實(shí)現(xiàn),用于完成依賴于CP冰系結(jié)構(gòu)的初始化,并調(diào)用第二

13、階段的代碼。第二階段由C語(yǔ)言實(shí)現(xiàn),完成相關(guān)初始化后,進(jìn)入命令循環(huán)以等待用戶命令,或?qū)?shù)傳給內(nèi)核,引導(dǎo)Linux內(nèi)核啟動(dòng)。圖中給出了Uboot的啟動(dòng)流程。Uboot-1.3.4中對(duì)at91rm9200dk系列的開發(fā)板有很好的支持,只需做少量修改即可使用。但是在目前U-Boot-1.3.4引導(dǎo)系統(tǒng)中,不能識(shí)別本論文中采用的8MBNORFlash!(SPANSIO淤司的S29GL064N90TFI04和1GBNANDFlash(SAMSUNG司的K9K8G08U0A兩款芯片,需要自行移植。4.Linux的編譯,內(nèi)核配置和裁剪4.1 Linux的編譯在配置內(nèi)核前的須做必要的設(shè)置,主要在內(nèi)核原碼中設(shè)置

14、文件Makefile,用下列指令打開Makefile文件:$viMakefile在Makefile中主要設(shè)置兩個(gè)地方:ARCHCROSSCOMPILE。ARCH:=arm;表示目標(biāo)板為arm。CROSSCOMPILE=交叉編譯工具的地址;設(shè)置交叉編譯工具的地址,例如CRoSSCOMPILE=lusr10calarm2953、birdarm1inux。還要在腳本文件mkimage中把路徑改為9200bootldru-boot-1.0.O/tools。(具體的路徑和你的u-boot放的位置有關(guān))然后按如下命令順序進(jìn)行內(nèi)核編譯即可:內(nèi)核配置:Smakemenuconfig或makcxeon!ig內(nèi)核

15、編譯:Smaketiean$makedep$make$./mkimage;運(yùn)行mkimage腳本文件4 2嵌入式Linux的配置和剪裁在Linux下,用makemenuconfig或makexeontig進(jìn)入酉己置界面。在內(nèi)核酉已置中,一般有四種選擇:Y(選擇)、N(不選)、M(模塊)和數(shù)字,用戶可以根據(jù)剪裁需要進(jìn)行設(shè)置,最后配置完畢,選擇是否對(duì)配置結(jié)果進(jìn)行保存?保存為eonfig文件。5 .嵌入式Linux文件系統(tǒng)的制作過程嵌入式系統(tǒng)可以使用硬盤和光盤,但是這與嵌入式系統(tǒng)的便攜式特性相違背,所以一般采用Flash作為存儲(chǔ)介質(zhì)。和硬盤相比,F(xiàn)lash有自己獨(dú)特的物理特性,所以必須使用專門的文件

16、系統(tǒng)。嵌入式系統(tǒng)對(duì)文件的操作是通過層次結(jié)構(gòu)實(shí)現(xiàn)的。對(duì)于用戶程序來說,文件是有結(jié)構(gòu)的文件,用戶程序通過文件IO函數(shù)操作文件。嵌入式文件系統(tǒng)是嵌入式系統(tǒng)的一部分,它的任務(wù)是對(duì)邏輯文件進(jìn)行管理,其工作包括提供對(duì)邏輯文件的操作(復(fù)制、刪除、修改等)接口,方便用戶操作文件和目錄。在文件系統(tǒng)的內(nèi)部,又根據(jù)存儲(chǔ)設(shè)備的特點(diǎn),適用不同的文件組織模式來實(shí)現(xiàn)文件的邏輯結(jié)構(gòu),比如磁帶終使用的順序文件以及大多數(shù)操作系統(tǒng)適用的樹狀文件。此外,文件系統(tǒng)要對(duì)管理文件的安全性負(fù)責(zé)。目前支持閃存的文件系統(tǒng)技術(shù)有以下幾種:eJFFS2和Yaffs。這些文件系統(tǒng)可以使用在沒有初始化的NANDFlash和有CFI接口的NORFlash

17、中。eTrueFFS,該文件系統(tǒng)相當(dāng)于Linux中的MTD層,必須配合其他文件系統(tǒng)。eFTLNTFL,它是一種中間層解決方案的統(tǒng)稱,為上層文件系統(tǒng)提供接口。eRAMFS、CRAMFS和ROMFS,這些文件系統(tǒng)用于早期的小容量閃存設(shè)備,系統(tǒng)功能比較簡(jiǎn)單,僅提供基本接口,只屬于只讀的閃存文件系統(tǒng)。適合存儲(chǔ)空間小的系統(tǒng)??砂凑杖缦虏襟E制作自己的文件系統(tǒng):解開壓縮的文件系統(tǒng):$gamzipramdiskgz文件系統(tǒng)掛載:$mount_oloopramdisk/mnt/nweramdisk(注:newramdisk是新建的目錄)。進(jìn)入newramdisk目錄進(jìn)行操作,隨意的增減文件:Sod/nmt/ne

18、wramdisk(注:進(jìn)入目錄后敲入命令隨意的增減文件)退出newramdisk目錄后御載文件系統(tǒng):Sumountmntnewramdisic壓縮文件系統(tǒng),生成新的文件系統(tǒng)映象:$gzip-c-、,9ramdisk>./newramdisk6 .Linux中交叉編譯器的搭建和環(huán)境變量的設(shè)置1 .安裝標(biāo)準(zhǔn)的C開發(fā)環(huán)境,由于Linux安裝默認(rèn)是不安裝的,所以需要先安裝一下(如果已經(jīng)安裝好的話,就可以免去這一步了):#sudoapt-getinstallgccg+libgccllibg+makegdb2 .下載arm-linux-gcc-341.tar.bz2到任意的目錄下。3 .解壓arm-

19、linux-gcc-3.4.1.tar.bz2#tar-jxvfarm-linux-gcc-3.4.1.tar.bz2解壓過程需要一段時(shí)間,解壓后的文件形成了usr/local/文件夾,進(jìn)入該文件夾,將arm文件夾拷貝到/usr/local/下#cdusr/local/#cp-rvarm/usr/local/現(xiàn)在交叉編譯程序集都在/usr/local/arm/3.4.1/bin下面。4 .修改環(huán)境變量,把交叉編譯器的路徑加入到PATH。方法一:修改/etc/bash.bashrc文件#vim/etc/bash.bashrc在最后加上:exportPATH=$PATH:/usr/local/ar

20、m/3.4.1/binexportPATH方法二:修改/etc/profile文件:#vim/etc/profile增加路徑設(shè)置,在末尾添加如下,保存/etc/proMe文件:exportPATH=$PATH:/usr/local/arm/3.4.1/bin方法三:#exportPATH=$PATH:/usr/local/arm/3.4.1/bin注:(這只能在當(dāng)前的終端下才是有效的!)5 .立即使新的環(huán)境變量生效,不用重啟電腦:對(duì)應(yīng)方法一:#source/root/.bashrc對(duì)應(yīng)方法二:#source/etc/profile6 .檢查是否將路徑加入到PATH:#echo$PATH顯示的內(nèi)

21、容中有/usr/local/arm/bin,說明已經(jīng)將交叉編譯器的路徑加入PATH。至此,交叉編譯環(huán)境安裝完成。7 .測(cè)試是否安裝成功#arm-linux-gcc-v上面的命令會(huì)顯示arm-linux-gcc信息和版本:Readingspecsfrom/usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/specsConfiguredwith:/work/crosstool-0.27/build/arm-linux/gcc-3.4.1-glibc-2.3.2/gcc-3.4.1/configure-target=arm-linux-host=i686-hos

22、t_pc-linux-gnu-prefix=/usr/local/arm/3.4.1-with-headers=/usr/local/arm/3.4.1/arm-linux/include-with-local-prefix=/usr/local/arm/3.4.1/arm-linux-disable-nls-enable-threads=posix-enable-symvers=gnu-enable-_cxa_atexit-enable-languages=c,c+-enable-shared-enable-c99-enable-long-longThreadmodel:posixgccve

23、rsion3.4.18.編譯HelloWorld程序,測(cè)試交叉工具鏈寫下下面的HelloWorld程序,保存為hello.c#include<stdio.h>intmain()printf("HelloWorld!/n");return0;執(zhí)行下面的命令:#arm-linux-gcc-ohellohello.c修改環(huán)境變量這一步修改/etc/profile文件在path中添力口arm-linux-gcc路徑if"'id-u、"-eq0;thenPATH="/usr/local/sbin:/usr/local/bin:/usr

24、/sbin:/usr/bin:/sbin:/bin:/usr/local/arm/3.4.1/bin"elsePATH="/usr/local/bin:/usr/bin:/bin:/usr/games"fi再source/etc/profile就可以刷新環(huán)境變量7.驅(qū)動(dòng)程序的編寫過程與關(guān)鍵點(diǎn)7.1 Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序的結(jié)構(gòu)所有的Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序遵循通用的接口。設(shè)計(jì)時(shí)采用的是面向?qū)ο蟮姆椒?。一個(gè)設(shè)備就是一個(gè)對(duì)象(device結(jié)構(gòu)),它內(nèi)部有自己的數(shù)據(jù)和方法。每一個(gè)設(shè)備的方法被調(diào)用時(shí)的第一個(gè)參數(shù)都是這個(gè)設(shè)備對(duì)象本身。這樣這個(gè)方法就可以存取自身的數(shù)據(jù)(類似面向

25、對(duì)象程序設(shè)計(jì)時(shí)的this引用)。一個(gè)網(wǎng)絡(luò)設(shè)備最基本的方法有初始化、發(fā)送和接收。deliverpackets|receivepacketsqueue|(dev_queue_xmit()|them(netif_rx()|methodsandvariables(initialize,open,close,hard_xmit,|interrupthandler,config,resources,status.)|send to hardware |receivcefromhardware|hardwaremedia|初始化程序完成硬件的初始化、device中變量的初始化和系統(tǒng)資源的申請(qǐng)。發(fā)送程序是在驅(qū)

26、動(dòng)程序的上層協(xié)議層有數(shù)據(jù)要發(fā)送時(shí)自動(dòng)調(diào)用的。一般驅(qū)動(dòng)程序中不對(duì)發(fā)送數(shù)據(jù)進(jìn)行緩存,而是直接使用硬件的發(fā)送功能把數(shù)據(jù)發(fā)送出去。接收數(shù)據(jù)一般是通過硬件中斷來通知的。在中斷處理程序里,把硬件幀信息填入一個(gè)skbuff結(jié)構(gòu)中,然后調(diào)用netif_rx()傳遞給上層處理。7.2 網(wǎng)絡(luò)驅(qū)動(dòng)程序的基本方法網(wǎng)絡(luò)設(shè)備做為一個(gè)對(duì)象,提供一些方法供系統(tǒng)訪問。正是這些有統(tǒng)一接口的方法,掩蔽了硬件的具體細(xì)節(jié),讓系統(tǒng)對(duì)各種網(wǎng)絡(luò)設(shè)備的訪問都采用統(tǒng)一的形式,做到硬件無關(guān)性。下面是最基本的方法。(1) 初始化(initialize)(2)打開(open)(3)關(guān)閉(stop)1.1) 4)發(fā)送(hard_start_xmit)(

27、5)接收(reception)(6)硬件幀頭(hard_header)1.2) 7)地址解析(xarp)1.3) 8)參數(shù)設(shè)置和統(tǒng)計(jì)數(shù)據(jù)1.4) 網(wǎng)絡(luò)驅(qū)動(dòng)程序中用到的數(shù)據(jù)結(jié)構(gòu)最重要的是網(wǎng)絡(luò)設(shè)備的數(shù)據(jù)結(jié)構(gòu)。定義在include/linux/netdevice.h里。1.5) 常用的系統(tǒng)支持7.4.1 內(nèi)存申請(qǐng)和釋放include/linux/kernel.h里聲明了kmalloc()和kfree()。用于在內(nèi)核模式下申請(qǐng)和釋放內(nèi)存。Void*kmalloc(unsignedintlen,intpriority);voidkfree(void*_ptr);與用戶模式下的malloc()不同,kma

28、lloc()申請(qǐng)空間有大小限制。長(zhǎng)度是2的整次方。可以申請(qǐng)的最大長(zhǎng)度也有限制。另外kmalloc()有priority參數(shù),通常使用時(shí)可以為GFP_KERNEL,如果在中斷里調(diào)用用GFP_ATOMIC參數(shù),因?yàn)槭褂肎FP_KERNEL則調(diào)用者可能進(jìn)入sleep狀態(tài),在處理R斷時(shí)是不允許的。Kfree()釋放的內(nèi)存必須是kmalloc()申請(qǐng)的。如果知道內(nèi)存的大小,也可以用kfree_s()釋放。7.4.2 request_irq()、free_irq()這是驅(qū)動(dòng)程序申請(qǐng)中斷和釋放中斷的調(diào)用。在include/linux/sched.h里聲明。Request_irq()M用的定義:intrequ

29、est_irq(unsignedintirq,void(*handler)(intirq,void*dev_id,structpt_regs*regs),unsignedlongirqflags,constchar*devname,void*dev_id);irq是要申請(qǐng)的硬件中斷號(hào)。在Intel平臺(tái),范圍0-15。Handler是向系統(tǒng)登記的中斷處理函數(shù)。這是一個(gè)回調(diào)函數(shù),中斷發(fā)生時(shí),系統(tǒng)調(diào)用這個(gè)函數(shù),傳入的參數(shù)包括硬件中斷號(hào),deviceid,寄存器值。Dev_id就是下面的request_irq時(shí)傳遞給系統(tǒng)的參數(shù)dev_id。Irqflags是中斷處理的一些屬性。比較重要的有SA_INT

30、ERRUPT,標(biāo)明中斷處理程序是快速處理程序(設(shè)置SA_INTERRUPT)還是慢速處理程序(不設(shè)置SA_INTERRUPT)??焖偬幚沓绦虮徽{(diào)用時(shí)屏蔽所有中斷。慢速處理程序不屏蔽。還有一個(gè)SA_SHIRQ屬性,設(shè)置了以后運(yùn)行多個(gè)設(shè)備共享中斷。Dev_id在中斷共享時(shí)會(huì)用到。一般設(shè)置為這個(gè)設(shè)備的device結(jié)構(gòu)本身或者NULL。中斷處理程序可以用dev_id找到相應(yīng)的控制這個(gè)中斷的設(shè)備,或者用irq2dev_map找到中斷對(duì)應(yīng)的設(shè)備。Voidfree_irq(unsignedintirq,void*dev_id);7.4.3 時(shí)鐘時(shí)鐘的處理類似中斷,也是登記一個(gè)時(shí)間處理函數(shù),在預(yù)定的時(shí)間過后,

31、系統(tǒng)會(huì)調(diào)用這個(gè)函數(shù)。在include/linux/timer.h里聲明。Structtimer_liststructtimer_list*next;structtimer_list*prev;unsignedlongexpires;unsignedlongdata;void(*function)(unsignedlong);voidadd_timer(structtimer_list*timer);intdel_timer(structtimer_list*timer);voidinit_timer(structtimer_list*timer);使用時(shí)鐘,先聲明一個(gè)timer_list結(jié)構(gòu),

32、調(diào)用init_timer對(duì)它進(jìn)行初始化。Time_list結(jié)構(gòu)里expires是標(biāo)明這個(gè)時(shí)鐘的周期,單位采用jiffies的單位。Jiffies是Linux一個(gè)全局變量,代表時(shí)間。它的單位隨硬件平臺(tái)的不同而不同。系統(tǒng)里定義了一個(gè)常數(shù)HZ,代表每秒種最小時(shí)間間隔的數(shù)目。這樣jiffies的單位就是1/HZ。Intel平臺(tái)jiffies的單位是1/100秒,這就是系統(tǒng)所能分辨的最小時(shí)間間隔了。所以expires/HZ就是以秒為單位的這個(gè)時(shí)鐘的周期。Function就是時(shí)間到了以后的回調(diào)函數(shù),它的參數(shù)就是timer_list中的dataData這個(gè)參數(shù)在初始化時(shí)鐘的時(shí)候賦值,一般賦給它設(shè)備的devi

33、ce結(jié)構(gòu)指針。在預(yù)置時(shí)間到系統(tǒng)調(diào)用function,同時(shí)系統(tǒng)把這個(gè)time_list從定時(shí)隊(duì)列里清除。所以如果需要一直使用定時(shí)函數(shù),要在function里再次調(diào)用add_timer()f巴這個(gè)timer_list加進(jìn)定時(shí)隊(duì)列。7.4.4 I/OI/O端口的存取使用:inlineunsignedintinb(unsignedshortport);inlineunsignedintinb_p(unsignedshortport);inlinevoidoutb(charvalue,unsignedshortport);inlinevoidoutb_p(charvalue,unsignedshortp

34、ort);在include/adm/io.h里定義。Inb_p()、outb_p()與inb()、outb_p()的不同在于前者在存取I/O時(shí)有等待(pause廠汨慢速的I/O設(shè)備。為了防存取I/O時(shí)發(fā)生沖突,Linux提供對(duì)端口使用情況的控制。在使用端口之前,可以檢查需要的I/O是否正在被使用,如果沒有,則把端口標(biāo)記為正在使用,使用完后再釋放。系統(tǒng)提供以下幾個(gè)函數(shù)做這些工作。Intcheck_region(unsignedintfrom,unsignedintextent);voidrequest_region(unsignedintfrom,unsignedintextent,constc

35、har*name);voidrelease_region(unsignedintfrom,unsignedintextent);其中的參數(shù)from表示用到的I/O端口的起始地址,extent標(biāo)明從from開始的端口數(shù)目。Name為設(shè)備名稱。7.4.5 中斷打開關(guān)閉系統(tǒng)提供給驅(qū)動(dòng)程序開放和關(guān)閉響應(yīng)中斷的能力。是在include/asm/system.h中的兩個(gè)定義。#definecli()_asm_volatile_("cli":)#definesti()_asm_volatile_("sti":)7.4.6打印信息類似普通程序里的printf(),驅(qū)動(dòng)程

36、序要輸出信息使用printk()。在include/linux/kernel.h里聲明。Intprintk(constchar*fmt,.);其中fmt是格式化字符串。.是參數(shù)。都是和printf()格式一樣的。7.4.7 注冊(cè)驅(qū)動(dòng)程序如果使用模塊(module)方式加載驅(qū)動(dòng)程序,需要在模塊初始化時(shí)把設(shè)備注冊(cè)到系統(tǒng)設(shè)備表里去。不再使用時(shí),把設(shè)備從系統(tǒng)中卸除。定義在drivers/net/net_init.h里的兩個(gè)函數(shù)完成這個(gè)工作。Intregister_netdev(structdevice*dev);voidunregister_netdev(structdevice*dev);dev就是

37、要注冊(cè)進(jìn)系統(tǒng)的設(shè)備結(jié)構(gòu)指針。在register_netdev()M,dev結(jié)構(gòu)一般填寫前面11項(xiàng),即到init,后面的暫時(shí)可以不用初始化。最重要的是name指針和init方法。Name指針空(NULL)或者內(nèi)容為'0或者name0為空格(space)則系統(tǒng)把你的設(shè)備做為以太網(wǎng)設(shè)備處理。以太網(wǎng)設(shè)備有統(tǒng)一的命名格式,ethX。對(duì)以太網(wǎng)這么特別對(duì)待大概和Linux的歷史有關(guān)。Init方法一定要提供,register_netdev(法調(diào)用這個(gè)方法讓你又t硬件檢測(cè)和設(shè)置。Register_netdev(返回0表示成功,非0不成功。7.4.8 sk_buffLinux網(wǎng)絡(luò)各層之間的數(shù)據(jù)傳送都是通過

38、sk_buff。Sk_buff提供一套管理緩沖區(qū)的方法,是Linux系統(tǒng)網(wǎng)絡(luò)高效運(yùn)行的關(guān)鍵。每個(gè)sk_buff包括一些控制方法和一塊數(shù)據(jù)緩沖區(qū)??刂品椒ò垂δ芊譃閮煞N類型。一種是控制整個(gè)buffer鏈的方法,另一種是控制數(shù)據(jù)緩沖區(qū)的方法。Sk_buff組織成雙向鏈表的形式,根據(jù)網(wǎng)絡(luò)應(yīng)用的特點(diǎn),對(duì)鏈表的操作主要是刪除鏈表頭的元素和添加到鏈表尾。Sk_buff的控制方法都很短小以盡量減少系統(tǒng)負(fù)荷。(translatedfromarticlewrittenbyAlanCox)常用的方法包括:.alloc_skb()申請(qǐng)一個(gè)sk_buff并對(duì)它初始化。返回就是申請(qǐng)到的sk_buff。.dev_allo

39、c_skb(段似alloc_skb,在申請(qǐng)好緩沖區(qū)后,保留16字節(jié)的幀頭空間。主要用在Ethernet驅(qū)動(dòng)程序。.kfree_skb()釋放一個(gè)sk_buff。.skb_clone()復(fù)制一個(gè)sk_buff,但不復(fù)制數(shù)據(jù)部分。.skb_copy()完全復(fù)制一個(gè)sk_buff。.skb_dequeue()從一個(gè)sk_buff鏈表里取出第一個(gè)元素。返回取出的sk_buff,如果鏈表空則返回NULL。這是常用的一個(gè)操作。.skb_queue_head()在一個(gè)sk_buff鏈表頭放入一個(gè)元素。.skb_queue_tail()在一個(gè)sk_buff鏈表尾放入一個(gè)元素。這也是常用的一個(gè)操作。網(wǎng)絡(luò)數(shù)據(jù)的處

40、理主要是對(duì)一個(gè)先進(jìn)先出隊(duì)列的管理,skb_queue_tail()和skb_dequeue(亢成這個(gè)工作。.skb_insert()在鏈表的某個(gè)元素前插入一個(gè)元素。.skb_append()在鏈表的某個(gè)元素后插入一個(gè)元素。一些協(xié)議(如TCP)對(duì)沒按順序到達(dá)的數(shù)據(jù)進(jìn)行重組時(shí)用到skb_insert()和skb_append(>.skb_reserve()在一個(gè)申請(qǐng)好的sk_buff的緩沖區(qū)里保留一塊空間。這個(gè)空間一般是用做下一層協(xié)議的頭空間的。.skb_put()在一個(gè)申請(qǐng)好的sk_buff的緩沖區(qū)里為數(shù)據(jù)保留一塊空間。在alloc_skb以后,中請(qǐng)到的sk_buff的緩沖區(qū)都是處于空(f

41、ree)狀態(tài),有一個(gè)tail指針指向free空間,實(shí)際上開始時(shí)tail就指向緩沖區(qū)頭。Skb_reserve(而free空間里申請(qǐng)協(xié)議頭空間,skb_put()申請(qǐng)數(shù)據(jù)空間。見下面的圖。.skb_push()把sk_buff緩沖區(qū)里數(shù)據(jù)空間往前移。即把Headroom中的空間移一部分到Dataarea。.skb_pull()把sk_buff緩沖區(qū)里Dataarea中的空間移一部分到Headroom中。|Tailroom(free)|Afteralloc_skb()|Headroom|Tailroom(free)|Afterskb_reserve()|Headroom|Dataarea|Tail

42、room(free)|Afterskb_put()|Head|skb_|Data|Tailroom(free)|room|push|Dataarea|Afterskb_push()|Head|skb_|Dataarea|Tailroom(free)|pull|Headroom|Afterskb_pull()7.5) 編寫Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序中需要注意的問題7.5.1 中斷共享Linux系統(tǒng)運(yùn)行幾個(gè)設(shè)備共享同一個(gè)中斷。需要共享的話,在申請(qǐng)的時(shí)候指明共享方式。系統(tǒng)提供的request_irq()調(diào)用的定義:intrequest_irq(unsignedintirq,void(*handler)(

43、intirq,void*dev_id,structpt_regs*regs),unsignedlongirqflags,constchar*devname,void*dev_id);如果共享中斷,irqflags設(shè)置SA_SHIRQ屬性,這樣就允許別的設(shè)備申請(qǐng)同一個(gè)中斷。需要注意所有用到這個(gè)中加勺設(shè)備在調(diào)用requestjrq()®必須設(shè)置這個(gè)屬性。系統(tǒng)在回調(diào)每個(gè)中斷處理程序時(shí),可以用dev_id這個(gè)參數(shù)找到相應(yīng)的設(shè)備。一般dev_id就設(shè)為device結(jié)構(gòu)本身。系統(tǒng)處理共享中斷是用各自的dev_id參數(shù)依次調(diào)用每一個(gè)中斷處理程序。7.5.2 硬件發(fā)送忙時(shí)的處理主CPU的處理能力一般

44、比網(wǎng)絡(luò)發(fā)送要快,所以經(jīng)常會(huì)遇到系統(tǒng)有數(shù)據(jù)要發(fā),但上一包數(shù)據(jù)網(wǎng)絡(luò)設(shè)備還沒發(fā)送完。因?yàn)樵贚inux里網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序一般不做數(shù)據(jù)緩存,不能發(fā)送的數(shù)據(jù)都是通知系統(tǒng)發(fā)送不成功,所以必須要有一個(gè)機(jī)制在硬件不忙時(shí)及時(shí)通知系統(tǒng)接著發(fā)送下面的數(shù)據(jù)。一般對(duì)發(fā)送忙的處理在前面設(shè)備的發(fā)送方法(hard_start_xmit)里已經(jīng)描述過,即如果發(fā)送忙,置tbusy為1。處理完發(fā)送數(shù)據(jù)后,石發(fā)送結(jié)束中斷里消tbusy,同時(shí)用mark_bh()調(diào)用通知系統(tǒng)繼續(xù)發(fā)送。但在具體實(shí)現(xiàn)我的驅(qū)動(dòng)程序時(shí)發(fā)現(xiàn),這樣的處理系統(tǒng)好象并不能及時(shí)地知道硬件已經(jīng)空閑了,即在mark_bh()以后,系統(tǒng)要等一段時(shí)間才會(huì)接著發(fā)送。造成發(fā)送效率很低。2M線路只有10%不到的使用率。內(nèi)核版本為2.0.35。我最后的實(shí)現(xiàn)是不把tbusy置1,讓系統(tǒng)始終認(rèn)為硬件空閑,但是報(bào)告發(fā)送不成功。系統(tǒng)會(huì)一直嘗試重發(fā)。這樣處理就運(yùn)行正常了。但是遍循內(nèi)核源碼中的網(wǎng)絡(luò)驅(qū)動(dòng)程序,似乎沒有這樣處理的。不知道癥結(jié)在哪里。7.5.3 流量控制(flowcontrol)網(wǎng)絡(luò)數(shù)據(jù)的發(fā)送和接收都需要流量控制。這些控制是在系統(tǒng)里實(shí)現(xiàn)的,不需要驅(qū)動(dòng)程序做工作。每個(gè)設(shè)備數(shù)據(jù)結(jié)構(gòu)里都有一個(gè)參數(shù)dev->tx_queue_len,這個(gè)參數(shù)標(biāo)明發(fā)送時(shí)最多緩存

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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)論