|   如何學習linux設備驅動  時間:2017-01-05作(zuo)者:華清遠見 Linux系統(tong)目(mu)前主要維護(hu)2.4和2.6兩個內(nei)(nei)核(he)(he)(he)版(ban)(ban)本,在//www.kernel.org/ 網(wang)站上(shang)已經可以下載到新(xin)的(de)(de)2.6內(nei)(nei)核(he)(he)(he)linux-2.6.38.6,及新(xin)的(de)(de)2.4內(nei)(nei)核(he)(he)(he)linux-2.4.37.11。穩(wen)定版(ban)(ban)本號基本上(shang)是1~3月更新(xin)一次(ci),如:2.6.35至(zhi)2.6.36,升(sheng)級(ji)版(ban)(ban)本號每1~2周更新(xin)一次(ci),如:2.6.35.1至(zhi)2.6.35.2。 升(sheng)級(ji)后(hou)的(de)(de)高版(ban)(ban)本內(nei)(nei)核(he)(he)(he)并不完(wan)全兼容(rong)低版(ban)(ban)本內(nei)(nei)核(he)(he)(he),所(suo)以內(nei)(nei)核(he)(he)(he)升(sheng)級(ji)對于從事(shi)linux開發的(de)(de)技(ji)術人員來說(shuo)影響很大,特別(bie)是對于那些剛剛從事(shi)linux開發的(de)(de)人員。 通(tong)常,內核(he)的(de)(de)(de)升級對從(cong)事linux應(ying)用程(cheng)序(xu)開(kai)發(fa)的(de)(de)(de)人(ren)員(yuan)來說(shuo)影響(xiang)較(jiao)小,因(yin)為(wei)系統調用基(ji)本(ben)保持兼容,影響(xiang)比較(jiao)大的(de)(de)(de)是驅動(dong)開(kai)發(fa)人(ren)員(yuan)。每次內核(he)的(de)(de)(de)更(geng)新(xin)都可能(neng)導致(zhi)(zhi)許多內核(he)函數(shu)原(yuan)型上(shang)的(de)(de)(de)變(bian)化(hua),其中既有內核(he)本(ben)身(shen)提供(gong)的(de)(de)(de)函數(shu),也(ye)有硬件平臺(tai)代(dai)碼提供(gong)的(de)(de)(de)函數(shu),后者(zhe)變(bian)化(hua)的(de)(de)(de)更(geng)加(jia)頻(pin)繁。這(zhe)一(yi)點從(cong)許多經典(dian)書籍就可驗證(zheng),當(dang)你按(an)照手里(li)的(de)(de)(de)經典(dian)著作,如:Alessandro的(de)(de)(de)《linux設備(bei)驅動(dong)程(cheng)序(xu)》,編(bian)寫驅動(dong)時,發(fa)現(xian)并不能(neng)夠(gou)成功的(de)(de)(de)在你的(de)(de)(de)linux平臺(tai)上(shang)編(bian)譯通(tong)過、或不能(neng)正常執行,原(yuan)因(yin)就在于(yu)你用的(de)(de)(de)內核(he)和書里(li)的(de)(de)(de)不一(yi)致(zhi)(zhi)。 本文從兩個方面去解釋這個問題,一方面是(shi)如(ru)何寫好(hao)linux設(she)備驅動,另一方面是(shi)如(ru)何應對不(bu)斷升級(ji)的內核。 如何寫好Linux設備驅動 Linux設備(bei)驅動是linux內核的一(yi)(yi)部分,是用(yong)來屏蔽(bi)硬件細節,為上層提供標(biao)準接口的一(yi)(yi)種技術手段。為了能夠編寫出質量(liang)比較高的驅動程序,要求工程師必須具備(bei)以下幾個方面的知識: ● 熟悉處理器的性能 如:處理(li)(li)器的(de)體系(xi)結(jie)構、匯編語言(yan)、工作模(mo)式(shi)、異常(chang)處理(li)(li)等。對于(yu)初學者(zhe)來說,在還不(bu)(bu)熟(shu)悉驅(qu)動(dong)編寫(xie)方法的(de)情況下,可(ke)以(yi)先不(bu)(bu)把重心放在這(zhe)一項(xiang)上,因為(wei)可(ke)能因為(wei)它的(de)枯燥、抽象(xiang)而影響到你(ni)對設備(bei)驅(qu)動(dong)的(de)興趣(qu)。隨著你(ni)不(bu)(bu)斷地熟(shu)悉驅(qu)動(dong)的(de)編寫(xie),你(ni)會很自然的(de)意識到此(ci)項(xiang)的(de)重要性(xing)。 ● 掌握驅動目標的硬件工作原理及通訊協議 如(ru):串口(kou)控制(zhi)器、顯(xian)卡控制(zhi)器、硬件(jian)編(bian)解碼、存(cun)儲(chu)卡控制(zhi)器、I2C通(tong)訊(xun)、SPI通(tong)訊(xun)、USB通(tong)訊(xun)、SDIO通(tong)訊(xun)、I2S通(tong)訊(xun)、PCI通(tong)訊(xun)等。編(bian)寫設備(bei)(bei)驅(qu)動(dong)(dong)的前提就是需要(yao)(yao)了解設備(bei)(bei)的操作方法(fa),所(suo)以(yi)這些(xie)內容(rong)的重要(yao)(yao)程度不言(yan)而喻。但(dan)不是說要(yao)(yao)把所(suo)有設備(bei)(bei)的操作方法(fa)都(dou)熟悉了以(yi)后才(cai)可(ke)以(yi)寫驅(qu)動(dong)(dong),你只需要(yao)(yao)了解你要(yao)(yao)驅(qu)動(dong)(dong)的硬件(jian)就可(ke)以(yi)了。 ● 掌握硬件的控制方法 如(ru):中斷、輪詢(xun)(xun)、DMA 等,通常一個硬件(jian)控制(zhi)器會(hui)有(you)多種控制(zhi)方法(fa),你需要根(gen)據(ju)系統性能的(de)(de)需要合理的(de)(de)選(xuan)擇操作方法(fa)。初學階(jie)段以實(shi)現(xian)功(gong)能為目的(de)(de),掌握的(de)(de)順序(xu)應該是,輪詢(xun)(xun)->中斷->DMA。隨(sui)著學習的(de)(de)深入,需要綜合考慮系統的(de)(de)性能需求,采取合適的(de)(de)方法(fa)。 ● 良好的GNU C語言編程基礎 如(ru):C語言的指(zhi)針、結構體、內存操作、鏈表、隊列、棧(zhan)、C和匯編混合(he)編程等。這些編程語法是編寫設備驅動(dong)的基礎,無(wu)論對于(yu)初(chu)學者還是有經驗者都非常重要。 ● 良好的linux操作系統概念 如:多進(jin)程(cheng)(cheng)、多線程(cheng)(cheng)、進(jin)程(cheng)(cheng)調度、進(jin)程(cheng)(cheng)搶占、進(jin)程(cheng)(cheng)上下文、虛擬內存、原子操作、阻塞、睡眠(mian)、同步(bu)等概念(nian)及它們(men)(men)之間(jian)的(de)關系。這些(xie)概念(nian)及方法在(zai)設備驅(qu)動(dong)里的(de)使用是linux設備驅(qu)動(dong)區別單片機編程(cheng)(cheng)的(de)大特點(dian),只有理解了它們(men)(men)才會編寫出高質量的(de)驅(qu)動(dong)。 ● 掌握linux內核中設備驅動的編寫接口 如:字符設(she)備(bei)的(de)(de)cdev、塊設(she)備(bei)的(de)(de)gendisk、網絡設(she)備(bei)的(de)(de)net_device,以(yi)及基于這(zhe)些基本接口的(de)(de)framebuffer設(she)備(bei)的(de)(de)fb_info、mtd設(she)備(bei)的(de)(de)mtd_info、tty設(she)備(bei)的(de)(de)tty_driver、usb設(she)備(bei)的(de)(de)usb_driver、mmc設(she)備(bei)的(de)(de)mmc_host等(deng)。 Linux內核為設(she)備(bei)驅動編寫(xie)者提(ti)供(gong)了標準(zhun)的(de)(de)接口,驅動編寫(xie)者無需精通內核的(de)(de)各個(ge)(ge)部分(fen),只需要明確內核提(ti)供(gong)給(gei)我們(men)的(de)(de)接口,并實現(xian)此接口就(jiu)可以(yi)了。內核提(ti)供(gong)的(de)(de)接口采用的(de)(de)是(shi)面向(xiang)對象(xiang)(xiang)的(de)(de)思路(lu),即把(ba)目標設(she)備(bei)抽象(xiang)(xiang)成一(yi)個(ge)(ge)對象(xiang)(xiang),通常利用一(yi)個(ge)(ge)結構體來描述這個(ge)(ge)對象(xiang)(xiang)。驅動工程師(shi)的(de)(de)任務就(jiu)是(shi)實現(xian)這個(ge)(ge)對象(xiang)(xiang)。這個(ge)(ge)結構體中會包含設(she)備(bei)的(de)(de)屬性(用變量表(biao)示)和操(cao)作方法(用函(han)數指針表(biao)示)。如:字符設(she)備(bei)的(de)(de)cdev 
	struct cdev { 開(kai)始階段可(ke)以以模(mo)(mo)仿為主,即套用一些(xie)固定(ding)的模(mo)(mo)板(ban)、參考例程(cheng)。 如何應對不斷升級的內核 內(nei)核(he)升級對驅動(dong)的(de)(de)影(ying)響(xiang)主要體現在,(1)驅動(dong)接口(kou)定義(yi)的(de)(de)變(bian)化;(2)內(nei)核(he)的(de)(de)一些(xie)功能函(han)數(shu)的(de)(de)名稱、參數(shu)、頭文件、宏(hong)定義(yi)的(de)(de)變(bian)化;(3)平臺代碼(ma)關于硬件操作方面(mian)封(feng)裝的(de)(de)一些(xie)函(han)數(shu)的(de)(de)變(bian)化;(4)設備模型(xing)的(de)(de)影(ying)響(xiang)。 ● 驅動接口定義的變化 如:2.4內核中字符(fu)設備驅動的注冊接口是: int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) 而2.6內核中已經不建(jian)議使用(yong)這種(zhong)方法了,改為: int cdev_add(struct cdev *p, dev_t dev, unsigned count) 這種接(jie)口定(ding)義及注(zhu)冊(ce)方(fang)(fang)法帶(dai)來的(de)變化,發生的(de)并不頻(pin)繁。解決方(fang)(fang)案是:參(can)考內核(he)中(zhong)的(de)代(dai)碼。這種接(jie)口定(ding)義及注(zhu)冊(ce)方(fang)(fang)法在內核(he)中(zhong)非常容易找到,如:字符設(she)備驅動(dong)的(de)注(zhu)冊(ce)方(fang)(fang)法及接(jie)口定(ding)義可以參(can)照內核(he)driver/char/目錄下的(de)很多(duo)實例。 ● 內核的一些功能函數的名稱、參數、頭文件、宏定義的變化 如:中斷(duan)注冊(ce)函數(shu)的格式及參數(shu)在(zai)2.4內核(he)、2.6內核(he)低版本和高版本之間都存在(zai)差別,在(zai)2.6.8中,中斷(duan)注冊(ce)函數(shu)的定義(yi)為(wei): int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),unsigned long irq_flags, const char * devname, void *dev_id) irq_flags的取值(zhi)主(zhu)要(yao)為下(xia)面的某一種或組合: SA_INTERRUPT、SA_SAMPLE_RANDOM、SA_SHIRQ 在2.6.26中,中斷注冊(ce)函數的定義為(wei): int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char *devname, void *dev_id) typedef irqreturn_t (*irq_handler_t)(int, void *); irq_flags的(de)取值(zhi)主要為(wei)下面的(de)某一種(zhong)或組(zu)合:(功能(neng)和2.6.8的(de)對應)IRQF_DISABLED、IRQF_SAMPLE_RANDOM、IRQF_SHARED 當出現這些問題(ti)時,編(bian)譯過程中(zhong),編(bian)譯器會給我們(men)比較明(ming)確的(de)錯誤提(ti)示,根據這些提(ti)示你可以(yi)判斷出是(shi)否是(shi)缺少(shao)頭文件問題(ti)、是(shi)否是(shi)函數(shu)參數(shu)定義(yi)有誤等。解決問題(ti)的(de)好辦法(fa)(fa)還是(shi)到你的(de)目標內核中(zhong)找(zhao)(zhao)信息。此時找(zhao)(zhao)問題(ti)的(de)方法(fa)(fa)可以(yi)借助于搜索,如(ru):你可以(yi)在新的(de)內核中(zhong)搜索request_irq,看新內核中(zhong)的(de)驅動是(shi)如(ru)何使用它的(de),這種方法(fa)(fa)非常有效。 ● 平臺代碼關于硬件操作方面封裝的一些函數的變化 內(nei)(nei)核中,硬(ying)件(jian)平臺相關(guan)的代碼(ma)(ma)在內(nei)(nei)核更(geng)新過(guo)程中變化比較頻繁,和我(wo)們(men)的設(she)備(bei)驅(qu)動(dong)也是息(xi)息(xi)相關(guan),所以在針對一(yi)個新內(nei)(nei)核編寫設(she)備(bei)驅(qu)動(dong)前,一(yi)定要熟悉(xi)你的平臺代碼(ma)(ma)的結構。有(you)時平臺雖(sui)然提(ti)供了內(nei)(nei)核要求(qiu)的接口函數,但使(shi)用(yong)起來功能卻并不完善。下面(mian)還(huan)是先舉個例(li)子說明平臺代碼(ma)(ma)更(geng)新對設(she)備(bei)驅(qu)動(dong)的影響。 如:在linux-2.6.8內核(he)中,調用set_irq_type(IRQ_EINT0,IRQT_FALLING);去(qu)設置S3C2410的(de)IRQ_EINT0的(de)中斷觸發信號(hao)類型,你會(hui)發現(xian)不會(hui)有什么效果(guo)。跟蹤代碼發現(xian)內核(he)的(de)set_irq_type函數(shu)需(xu)要平臺(tai)提供一個針(zhen)對硬件平臺(tai)的(de)實(shi)現(xian)函數(shu) 
	static struct irqchip s3c_irqext_chip = { 
	s3c_irqext_type就是linux內核需要的實現函數,而s3c_irqext_type在2.6.8中的實現為: static int s3c_irqext_type(unsigned int irq, unsigned int type) 原(yuan)來(lai)并沒(mei)有實現(xian)。而在較高版(ban)本的(de)內核,如2.6.26內核中(zhong),這個函數是實現(xian)了(le)的(de)。所(suo)以你一定(ding)要小心(xin)。當平臺函數不(bu)好用時,一定(ding)要查查原(yuan)因,或(huo)者直接操作硬件寄(ji)存(cun)器(qi)來(lai)達到目(mu)的(de)。 ● 2.6內核設備模型對驅動的影響 在2.6內核(he)(he)中(zhong)(zhong)寫設(she)(she)備驅(qu)動和在2.4內核(he)(he)中(zhong)(zhong)有(you)著很大的(de)不同,主要(yao)就是(shi)(shi)在設(she)(she)備驅(qu)動中(zhong)(zhong)融入了比設(she)(she)備驅(qu)動本(ben)身結構還(huan)(huan)復雜、還(huan)(huan)難以(yi)理(li)解的(de)設(she)(she)備模型。初學驅(qu)動時(shi)你(ni)可(ke)以(yi)不理(li)會(hui)設(she)(she)備模型,但你(ni)會(hui)發現內核(he)(he)里的(de)驅(qu)動代碼基本(ben)上都是(shi)(shi)融入了設(she)(she)備模型的(de)了。所以(yi)很多時(shi)候你(ni)不得(de)不面對現實(shi),還(huan)(huan)是(shi)(shi)要(yao)弄懂它,并且它也的(de)注冊(ce)方法也會(hui)隨著內核(he)(he)的(de)升級而發生變化。解決此類(lei)問題的(de)好(hao)方法還(huan)(huan)是(shi)(shi)參(can)考目標內核(he)(he)驅(qu)動代碼。 總結: 開始(shi)學習設備驅動時,選擇一個當前比較流(liu)行的(de)內核版本和(he)硬件(jian)平臺,不(bu)急(ji)于追趕新潮流(liu)。這(zhe)樣你(ni)(ni)可以(yi)找(zhao)到(dao)的(de)網(wang)絡資(zi)源會比較多(duo),不(bu)至于有孤軍奮戰的(de)感(gan)覺(jue)。我想這(zhe)個過程(cheng)應該不(bu)低于1年(nian)。當過了(le)這(zhe)個過程(cheng)后,嘗(chang)試將你(ni)(ni)編寫過的(de)驅動移植到(dao)各(ge)個目標(biao)平臺上。 (本文參考了一些網上資料(liao),因原出處(chu)不詳,特向資料(liao)的原作者致謝!) 
 相關資訊 發表評論 
 |