寫在前面:本博客為本人原創,嚴禁任何形式的轉載!本博客只允許放在博客園(.cnblogs.com),如果您在其他網站看到這篇博文,請通過下面這個唯一的合法鏈接轉到原文!
本博客全網唯一合法URL:https://www.cnblogs.com/acm-icpcer/p/8029656.html
最近學院里的nfc老師要我們做個設備驅動,之前從沒接手過這個東西,加上老師給的材料錯誤也是一大堆,搞了差不多一個星期才搞出來。特此寫一個博客,以免后來人和我一樣跳坑。
總體考慮
要去寫設備驅動程序,說白了就三大步驟:下載內核源碼構建內核源碼樹(也就是下載你的目的內核源碼包並解壓就行了)、編譯內核(這樣才能讓操作系統感知自己寫的驅動程序)、寫代碼(編寫內核程序並編譯測試)。這三步哪一步都很艱難。
我是在自己筆記本上用虛擬機VMware裝的ubuntu操作系統,相比於裝雙系統有一大缺點和一大優點,優點是將編譯好的新內核裝入操作系統時不用擔心系統崩潰,缺點是裝虛擬機的時候沒考慮周全,搞得虛擬機的硬盤太小了,估計容量不夠用。
那么綜合考慮之后,對於我來說是四大步驟:1、給虛擬機擴容;2、下載內核源碼構建內核源碼樹;3、編譯內核;4、寫代碼。
下面來一一介紹:
1、虛擬機擴容
(1)虛擬機邏輯擴盤。僅僅在這一步擴盤是完全不夠的!還要在虛擬機內部設置掛載,不然的話虛擬機無法感知到你擴展的硬盤。這相當於你給一台實際的台式電腦加了一塊新硬盤后,還要在操作系統內進行設置。我在這里是擴成80GB。
(2)在終端使用命令
sudo apt-get install Gparted
下載Gparted部件。
(3)打開Gparted:
(4)打開Gparted應用,你可以看到已分配分區狀況和新增未分配的分區 :
(5)然后依次刪除/dev/sda5和/dev/sda2,刪除后,就會剩下/dev/sda1(14GB)和未分配的(15GB),不然的話你怎么都無法將unallocated部分掛載。
(6)接下來重新調整/dev/sda1的大小,我這里調整為75529MiB(73.76GB),然后剩下6.24GB作為linux_swap,重新將未分配的6.24GB格式化,先new出一個extended的分區,然后再在這個extended的分區里new一個邏輯分區,並且file system選擇為linux-swap,最后選擇綠色的鈎鈎,完成保存。最后執行完后,如下圖所示:
(7)這樣我就把虛擬機的硬盤擴成了80GB,編譯內核源碼絕對是綽綽有余的了。
(注:本小節參考了博客:http://blog.csdn.net/Timsley/article/details/50742755)
2、構建內核源碼樹
(1)我的虛擬機的操作系統是ubuntu16.04。我是在這里下載的源碼包:https://www.kernel.org/pub/linux/kernel/v4.x/,我下載的源碼包是linux-4.10.14.tar.xz
附:大家千萬不要在非www.kernel.org開頭的網站上隨意下載內核源碼!
(2)下載完之后解壓即可:
3、編譯內核
(1)安裝基本的工具軟件。
逐次在終端執行以下四條命令:
sudo apt-get install libncurses5-dev libssl-dev sudo apt-get install build-essential openssl sudo apt-get install zlibc minizip sudo apt-get install libidn11-dev libidn11
(2)在終端進入你的解壓的內核源碼的目錄,比如我內核源碼解壓后在home/expr/expr4/linux-4.10.14,那么進入終端后就是:
(3)依次執行以下三條命令:
sudo make mrproper
sudo make clean
sudo make menuconfig
其中mrproper為清除編譯過程中產生的所有中間文件,clean為清除上一次產生的編譯中間文件,在menuconfig中出現選擇的圖形化界面后,直接按右方向鍵選擇到exit退出,退出提示中選擇保存,實現內核的默認配置。
(4)執行命令:
sudo make –j8
因為我的筆記本cpu是i7四核八線程,所以我直接用8個線程並行編譯,這樣編譯速度就是普通的make命令的8倍。最近雙一流建設學校發了財換了一大批新電腦,所以在我學校的高性能計算實驗室編譯內核,因為處理器是新買的intel core i7 6700k,8線程編譯的話20分鍾就搞定了,普通筆記本應該要1~2小時。
下面放一波編譯的時候截的圖:
正在編譯內核
編譯的時候監測筆記本狀態,怕內存泄漏
(5)依次執行命令:
sudo make modules_install //安裝內核模塊
sudo make install //安裝內核
下面放一波編譯的時候截的圖:
正在執行sudo make modules_install
正在執行sudo make modules_install
正在執行sudo make install
新內核成功嵌入操作系統
(6)重新啟動系統,如果是虛擬機的話記得重啟進入BIOS界面之前一定要點擊鼠標進入虛擬機的界面實現鍵盤捕獲。在重啟開機界面按住shift鍵不放手,選擇高級選項,進入內核選擇加載界面,選擇自己編譯的內核的正常模式:
進入內核選擇模式,選擇自己編譯的內核:
(7)至此,工作完成了50%。隨着操作系統的啟動,我新編譯的內核也正式誕生了!
(注:本小節參考了博客:http://blog.csdn.net/Xiaobai__Lee/article/details/72048829)
4、寫自己的設備驅動程序
(1)寫在前面:
在編程的時候,不要輕易復制任何網站的代碼,99.99%都是跑不通的。Makefile文件尤其不要隨便在網上下載,因為這個東西對格式要求非常高,新手隨便在網上下的Makefile文件也是99.99%都是跑不通。要跑通,有兩個關鍵:1、認真分析每一條源代碼;2、有問題,多去搜一下看看。
(2)我在ubuntu下編寫的代碼如下:
源代碼材料包托管在github上:https://wnm1503303791.github.io/interesting-work/blog/code.zip
有需要的朋友自取
(3)要在內核態下編譯我們寫好的設備驅動程序源碼,必須使用Makefile文件。
Makefile文件內容截圖,每個關鍵字都出現彩色的時候說明基本上沒寫錯
(4)在終端下進入設備驅動程序源碼所在的文件夾,例如,我的源碼放在home/expr/expr4/expr4/code/,那么就是這樣:
(5)輸入make命令,之后在文件夾下直接生成.ko文件:
(6)繼續在終端下輸入命令:sudo insmod globalmem.ko將剛剛生成的globalmem.ko文件加載進入內核。
(7)用命令lsmod查看是否加載成功,如果成功就是這樣:
可以看到第一個module就是我剛剛生成的globalmem。
(8)到這里工作完成了85%。可以先不急着去寫測試程序,可以先用原語測試一下驅動,因為我的這個驅動是處理字符的驅動程序,所以我是這樣測試的:
也就是進入root模式后用原語將字符串“tz”送入驅動,驅動就會輸出“tz”。
(9)現在就可以踏踏實實地去寫測試程序了:
(10)編譯這個C程序,並運行:
測試程序運行正常,表明設備驅動運行正常。
至此,我的教程就結束了。有疑問的朋友可以直接在評論區留言,非常希望和各位朋友一起討論!
TZ@華中農業大學信息學院高性能計算實驗室
2017/12/12夜
Last updated @ 2020/6/21