【學習筆記】linux
Linux三大設備驅動shell
IO的傳輸過程是以字符爲單位的,沒有緩衝。好比I2C,SPI都是字符設備ubuntu
IO傳輸過程當中是以塊爲單位的。跟存儲相關的,都屬於塊設備,好比:tf卡bash
與前兩個不同,是以socket套接字來訪問的。網絡
其中,理解和掌握字符設備驅動的概念最重要,由於在工做中咱們遇到大部分都是字符設備socket
(1)頭文件ide
(2)驅動模塊的入口和出口學習
(3)聲明信息命令行
(4)功能實現code
第一步,包含頭文件
第二步,驅動模塊的入口和出口
module_init();
module_exit();
第三步,生命模塊具備開源許可證
MODULE_LICENSE("GPL");
第四步,功能的實現
簡單的helloworld驅動程序編寫
/兩個必要的頭文件 #include <linux/init.h> #include <linux/module.h> //內核加載的時候打印hello world,內核模塊卸載的時候打印bye bye static int hello_init(void){ printk("hello world\n"); //內核裏不能使用c語言庫,因此不能用printf return 0; } static void hello_exit(void){ printk("bye bye\n"); } //入口和出口 module_init(hello_init); module_exit(hello_exit); //聲明許可證 MODULE_LICENSE("GPL");
把驅動編譯成模塊,而後使用命令把驅動加載到內核裏面。
步驟
一、編譯成模塊
(1)先寫一個makefile
在linux下
touch Makefile #建立Makefile文件
obj-m +=HelloWorld.o #obj-m 意爲把驅動編譯爲模塊 KDIR:={core_path} #PATH根據開發板內核路徑來填寫 PWD?=$(shell pwd) #自動獲取當前位置路徑 all: make -C $(KDIR) M=$(PWD) modules #切換到內核路徑,用make把代碼編譯成模塊
(2)編譯驅動
編譯驅動以前須要注意的問題:
內核源碼必定要編譯經過
編譯驅動用的內核源碼必定要和開發板上運行的內核鏡像是同一套
看一下開發代碼的ubuntu環境是否是arm,若是不是,要改爲arm環境
查看環境的 方法
在內核源碼的目錄下輸入
make menuconfig #顯示系統環境 #左上角若是顯示是X86,而不是arm,則輸入 export ARCH=arm #改成arm環境
爲了以防萬一,編譯前,先命令行輸入兩行代碼,設置環境和編譯器
export ARCH=arm export CROSS_COMPILE={編譯器名稱} #能夠直接輸入arm查看 #若是查看到:arm-linux-gnueabihf-gcc-4.9.4
編譯成功後就能夠看到 ko 文件了,這個 ko 文件就是編譯好的驅動。
在開發板上加載驅動用insmod
insmod HelloWorld.ko
查看加載的模塊,使用lsmod命令
lsmod
卸載驅動模塊
rmmod HelloWorld #注意這裏沒有後綴
卸載時,若是提示沒有相應的目錄,直接在對應的目錄下建立就能夠了
直接把驅動編譯到內核。
在下面有實際的例子。
若是芯片的內核不支持設備的驅動,那麼就須要把這個驅動移植到內核。
移植驅動須要驅動源碼和makefile。
(1)先去內核源碼搜索,若是有的話,能夠直接選擇這個驅動,而後直接使用。
(2)假如沒有這個驅動,則許喲啊本身編譯一個驅動,而後加載到內核裏邊去運行。
一、如何進入make menuconfig圖形化配置
首先進入到內核源碼的路徑下,而後輸入make menuconfig 便可打開這個界面。
二、make menuconfig圖形化界面的操做
(1)搜索功能
輸入「/」便可彈出搜索界面
(2)配置驅動狀態
把驅動編譯成模塊(用[ M ]來表示)
把驅動編譯到內核裏(用[ * ]來表示)
不編譯(用[ ]來表示)
可使用「空格」鍵來配置這三種不一樣的狀態
(3)如何退出
分爲保存退出和不保存退出,按照提示選擇便可
(4)和make menuconfig 有關的文件
Makefile:裏邊是編譯規則,高速咱們在make的時候須要如何編譯(至關於菜的作法)
Kconfig:內核配置的選項(至關於服務員給的菜單)
.config:配置完內核之後生成的配置選項(至關於我門勾選的菜單)
(5)make menuconfig會讀取不一樣環境目錄下的Kconfig文件
會讀取Arch/$ARCH/目錄下(目錄下有不少不一樣的環境文件夾)的Kconfig文件(選擇不一樣的環境,和export ARCH=arm效果相似)。
/arch/arm/configs 下面有不少配置文件(至關於特點菜,默認配置,在不知道如何配置的時候能夠按照這個來),若是移植內核的時候,配置文件太多,就能夠把這個文件夾下面的配置複製成.config裏邊(即默認系統的配置)【複製用cp命令】
(6)爲何要複製成.config,而不是其餘名字
由於內核會默認讀取Linux內核根目錄下的.config做爲默認的配置選項,因此不能夠更名字
(7)若是複製的默認配置.config不知足咱們的要求,如何解決
直接輸入make menuconfig,進入Kconfig配置界面,來進行修改配置,保存退出,配置會自動更新到.config裏面。
(8)配置文件選項怎樣和Makefile文件創建聯繫
當make menuconfig保存退出之後,Linux會將全部的配置選項以宏定義的形式保存在include/generated/下面的autoconf.h頭文件中。
#例子 source "drivers/redled/Kconfig" config LED_4412 tristate "Led Support for GPIO Led" depends on LEDS_CLASS help This option enable support for led #解讀 source "drivers/redled/Kconfig"#會讓config菜單裏邊包含drivers/redled/這個路徑下的驅動文件,方便咱們對菜單進行管理 config LED_4412 #配置選項的名稱,全名是CONFIG_LED_4412,這裏作了一些省略 tristate "Led Support for GPIO Led" #tristate表示驅動的狀態:1.把驅動編譯成模塊 2.把驅動編譯到內核 3.不編譯。與之對用的還有bool關鍵字:表示編譯到內核,和不編譯兩種狀態。 #"Led Support for GPIO Led"是make menuconfig裏邊的某個菜單的名字 depends on LEDS_CLASS # A depends on B表示只有在選擇B的時候才能夠選擇A,即A依賴於B。 #好比想要去掉LED相關的驅動,咱們雖然能夠直接改.config文件,可是不推薦這樣作。由於若是有依賴項的話,直接改.config文件是不成功的。 #select:反向依賴,該選項被選中時,後面的定義也會被選中。 help This option enable support for led #顯示幫助信息
把HelloWorld驅動編譯到內核。
(1)首先進入到內核源碼的目錄下(內核根目錄)
(2)把HelloWorld.c驅動,複製到drivers/char/hello文件夾【char通常就是放字符設備的文件夾,hello文件夾使用mkdir命令建立】
(3)寫Kconfig文件
mkdir hello #建立hello文件夾 cd hello/ #切換到hello文件夾 cp /home/pyma/HelloWorld.c #把驅動文件複製到hello文件夾中 touch Kconfig #建立一個Kconfig文件 vi Kconfig #打開Kconfig進行編輯 #寫程序 config HELLO #起個名字叫HELLO tristate "hello world" #選擇三種狀態的方式,並把菜單名字命名爲hello world #過於簡單沒有依賴,不用寫 help hello help #幫助信息爲hello help
保存退出
(4)寫Makefile文件
touch Makefile #建立Makefile文件夾 vi Makefile #打開Makefile編輯 #寫程序 obj-$(CONFIG_HELLO)+=HelloWorld.o
CONFIG_HELLO這個變量名字來源:是剛剛在Kconfig中命名的,可是Kconfig中至關於省略了CONFIG_,在這裏至關於補上,即:makfile中要寫全名。
$(CONFIG_HELLO)變量做用:會根據咱們選擇的狀態來改變,(1)若是是選擇把它編譯到內核中,那麼表示-y(即:obj-y)(2)若是選擇編譯成模塊,那麼它表示-m(即:obj-m)
到此,全部的文件都準備完成,接下來須要
(5)把hello驅動配置包,包含進去
須要修改上一級目錄的Makefile和Kconfig
cd .. #返回上一級目錄,即路徑.../char/ vi Makefile #修改Makefile,若是沒有則須要本身建立,本身寫 #寫程序,在首行添加如下代碼 obj-y +=hello/ #這裏注意hello是個文件夾,所以最後要加"/" ... #原有的makefile代碼 #保存退出 vi Kconfig #打開Kconfig文件,把剛纔寫的驅動代碼的Konfig包含進config菜單界面中 #在前面相應位置添加好Kconfig的路徑 source "drivers/char/hello/Kconfig" #Kconfig相對路徑 #保存退出
(6)回到內核根目錄下,打開菜單,選擇不一樣狀態
make menuconfig #進入配置菜單
在界面中選擇Device Drivers選項進入
再進入到Character devices目錄下
就會看到新添加的hello world驅動菜單項(名字是在Kconfig中命名的)
用空格鍵選擇狀態:
(7)編譯進內核,選擇<*>(編譯到內核)
保存退出,而後確保配置正確與否
打開.config文件,搜索
vi .config #打開配置文件 #搜索HELLO #搜索命令 /HELLO 若是出現CONFIG_HELLO=y是編譯到內核中了,m是編譯成模塊 這裏能夠看出,若是沒有依賴項,也能夠直接改.config文件的CONFIG_HELLO項
(8)編譯前更改
這時還不能立馬編譯,由於編譯會調用默認的的編譯配置,須要作相應修改
這裏爲了理解的透徹,先看一下編譯腳本:vi create.sh
#!/bin/bash export ARCH=arm ... make imx_v7_defconfig #這個就是內核的默認用法,意思是在編譯的時候會本身去找arch/arm/configs下面的imx_v7_defconfig配置文件,做爲.config來編譯內核。 ...
雖然前面咱們改了.config文件,但不是直接用它來編譯的,而是使用默認的arch/arm/configs/imx_v7_defconfig文件來編譯的。
所以還要再改一下
make distclean,清除全部的編譯文件,也刪掉了.config文件
把缺省配置複製到.config中
cp arch/arm/configs/imx_v7_defconfig .config
再進行第(6)步操做(這裏感受有點亂,步驟重複了?(6)、(7)兩步能夠不要)
(9)鍵修改後的.config複製回默認編譯菜單裏
cd arch/arm/configs/ #切換到默認配置目錄 mv imx_v7_defconfig imx_v7_defconfig_noHELLO #更改默認配置的名字 cp ../../../.config imx_v7_defconfig #把修改好的配置,更改成默認的名稱
(10)運行腳本,等待編譯完成
./create.sh
(11)檢驗是否編譯成功
方法一:燒寫到開發板上,運行看看有沒有加載驅動
cp arch/arm/boot/zImage /home/pyma/ #把鏡像複製到好找的位置
方法二:進入到建立的驅動目錄,查看有沒有把.c文件編譯成.o文件
cd drivers/char/hello/ ls
若是沒有相應的.o文件,則說明編譯出錯,檢查Makefile和其餘文件。
修改好,再回到根目錄編譯
.o文件檢查沒有問題後,再回到根目錄檢查是否有zImage鏡像
ls arch/arm/boot/