作者:machinnneee 說玩轉驅動這話,其實有點過頭,玩驅動是個長期積累的過程,寫出來是一回事,調試起來也是一種磨練。為了讓大家明白玩驅動的樂趣和掌握編寫驅動的捷徑,我分享一些經驗,算是拋磚引玉。不過正所謂一口吃不了個胖子,只有寫夠了足夠多的代碼,調試了足夠多的模塊,玩轉驅動也不再話下。希望今天的嘮叨對想踏入或者即將踏入驅動行業的你有些幫助。 我們很明白Linux 設備驅動的學習是一項浩大的工程,正是由于這個原因,一些人不免望而生畏,其實,只要我們有足夠的積累和全面的知識,玩轉驅動,也是早晚的事。閑話少說,開始來干貨。 對于驅動工程師來說,首先要明白驅動在整個系統中的作用, ![]() 大家從上圖中可以看出,linux驅動②在這個構架中起到承上硬件①啟下應用程序③的作用。在程序的編寫中,我們常用高內聚低耦合的標準,因此,驅動的引入顯得意義更加重大:一方面,使嵌入式應用工程師不用考慮過多的硬件差異,另一方面,通過將設備驅動融入內核,面向操作系統內核的接口,這樣的接口由操作系統規定,對一類設備而言結構一致,獨立于具體的設備。同時由于linux操作系統有內存管理和進程管理,因此對于多任務并發的要求時,操作系統和驅動的引入使得任務變得簡單。但是對于不需要多任務調度、文件系統、內存管理等復雜功能時,在一個大while(1)循環中既可以完成相關的任務。 上面分析了驅動的意義,那么,玩轉linux驅動需要那方面的知識呢,現在羅列下: 第一、Linux 驅動工程師要有良好的硬件基礎。 這個要求不言而喻,linux驅動工程師的主要任務就是隱藏硬件的差異,給應用工程師一個統一的接口,因此需要能看懂電路圖,理解SRAM、Flash、SDRAM、磁盤等模塊的讀寫方式,知道UART、I2C、USB 等設備的接口以及常規操作,了解輪詢、中斷、DMA 的原理,PCI 總線的工作方式以及CPU 的內存管理單元(MMU)等。不過對于這種常見的模塊,linux內核中有相關的配置,因此需要有閱讀linux內核的能力和修改linux內核的能力。 第二 、Linux驅動工程師具有良好的C 語言基礎。 作為一個面向硬件底層和應用層的關鍵人物,C語言功底是必須要牢固的。在編寫linux的字符設備和塊設備驅動中常用的fopen()、fwrite()、fread()、fclose()以及內存分配中經常使用結構體和指針。因此能靈活地運用C 語言的結構體、指針、函數指針及內存動態申請和釋放顯現的尤為重要。 例如字符設備驅動中的讀函數函數的定義 /* 讀設備*/ ssize_t xxx_read(struct file *filp, char _ _user *buf, size_t count,loff_t*f_pos) { ... copy_to_user(buf, ..., ...); ... } 從中看出C語言功底的重要性。 第三、 Linux 驅動工程師具有一定的Linux 內核基礎,雖然并不要求工程師對內核各個部分有深入的研究,但至少要了解設備驅動與內核的接口,尤其是對于塊設備、網絡設備、Flash設備、串口設備等復雜設備。 現在工作起來,嵌入式驅動工程師的工作量相對會小一點,因為一般常見的硬件設備供應商都會提供相應的linux版本驅動,驅動工程師的任務就是調試這些驅動能正常運行在自己的系統中,同時保證系統的穩定。 第四、 Linux 驅動工程師具有良好的操作系統知識。 這個要求對于沒有學習過操作系統的人來說唯一的痛苦之處就是對于專有名詞不是很理解,例如上半部,下半部,原子操作等。其實剛開始或許是個痛苦的過程,但是只要認真的分析了一個或者幾個驅動程序后,你就會發現其中的規律。畢竟linux驅動大體分為字符設備驅動、塊設備驅動和網絡設備驅動三類,正所謂抓其綱要,舉一反三,便可融會貫通。因此linux中多任務并發控制和同步等基礎很重要,因為在設備驅動中會大量使用自旋鎖、互斥、信號量、等待隊列等并發與同步機制。 第五、動手能力。 紙上得來終覺淺,因此,看再多的書也沒有真正的調試一個驅動來的認識深刻。這時你需要搭建宿主機平臺,購買開發板。不要好大喜功,從簡單的小驅動開始一步一步走,以螞蟻啃骨頭的精神進行學習,收獲會很大。 經歷了痛苦的折磨,現在看下嵌入式驅動工程師的甜蜜吧,工作個三五年,你已經是大師了,可以去招聘網站瀏覽下,這方面的待遇都是面議獎金都是大大的,紅色票票也隨心所愿了。想到這些,你還不下定決心來經受linux驅動的虐待,相信只要以“驅動虐我千百遍,我待驅動如初戀”的決心,相信你可以玩轉linux驅動。 |