01Linux驅動模組01
阿新 • • 發佈:2020-12-06
一、驅動基礎
1、什麼是驅動
能夠通過軟體操作硬體的這份程式就是驅動
2、Linux驅動和ARM裸機驅動的區別
1)Linux裝置驅動工作時依賴於Linux核心, ARM裸機驅動不依賴於Linux核心,可以單獨執行。
2)Linux裝置驅動工作的空間在核心空間的【3G~4G】中,驅動中不能有main函數出現,也不能有while(1)的死迴圈, ARM裸機驅動的程式碼都在一個main函式中編寫完成的。
3)Linux裝置驅動可以並行執行(核與核之間可以並行執行,單個核時也可以分時複用執行) ARM裸機驅動的程式是在一個while中分時複用執行的
3、驅動在核心中的位置
------------------------------------------------------------------------------ user(應用層): APP APP glibc(C標準庫) ----------------------------------------------------- shell: -----------------系統呼叫(swi軟中斷)------------------------------------------- kernel(核心層):(5大功能) 1)檔案管理 2)記憶體管理 3)程序管理 4)網路管理:網路協議棧管理(網路的幾個層次,TCP/IP四層、OSI七層) 5)裝置管理:裝置驅動管理 ----------------------------------------------------------------------------- hardware(硬體層): LED、滑鼠、鍵盤、LCD(幀快取)、camera、音效卡 emmc、U盤、硬碟、dm9000、TRL8211 -----------------------------------------------------------------------------------------------
4、驅動的種類
1)字元裝置驅動:
按照位元組流來訪問,並且只能順序訪問,不能無序訪問的裝置。
2)塊裝置驅動:
按照block(塊 = 512位元組)來訪問,可以順序訪問,也可以無序訪問的裝置。
3)網絡卡裝置驅動:
和網路通訊相關的裝置驅動,沒有裝置檔案,只能通過socket介面來訪問的裝置驅動
5、Linux核心模組
Linux核心模組的三要素:
1)入口: 驅動資源的申請,驅動物件的註冊
2)出口: 驅動資源的釋放,驅動資源的登出
3)許可證: 遵循 GPL 協議
GNU:GNU IS NOT UNIX 一個提倡軟體自由的組織--->理查德·斯托曼提出的
GPL:GNU通用公共許可證 一種協議
C語言為面向過程的語言,C++為面向物件的語言
驅動使用的是C語言程式設計,但要有面向物件的思想和概念
模組的編寫:!!!
1 #include <linux/init.h> 2 #include <linux/module.h> 3 4 //入口 5 static int __init mycdev_init(void) 6 { 7 //__init作用:告訴編譯器將mycdev_init這個函式放到.init.text這個段中 8 return 0; 9 } 10 11 //出口 12 static void __exit mycdev_exit(void) 13 { 14 //__exit作用:告訴編譯器將mycdev_exit這個函式放到.exit.text這個段中 16 } 17 18 module_init(mycdev_init); 19 //告訴核心入口函式的地址是mycdev_init 20 module_exit(mycdev_exit); 21 //告訴核心出口函式的地址是mycdev_exit 22 MODULE_LICENSE("GPL"); 23 //許可證 24
系統關鍵字
1、vi -t __ini
vim ./include/linux/init.h +44
44 #define __init __section(.init.text) __cold notr 驅動模組入口段
2、vi -t __exit
vim ./include/linux/init.h +83
83 #define __exit __section(.exit.text) __exitused __cold notrace 驅動模組出口段
以"__"開頭的內容,是給編譯器使用的,不需要太過理解,
如 __init、__exit、__FILE__、__func__、__LINE__
static 關鍵字
在模組的入口函式和出口函式中使用了 static 關鍵字進行了修飾
作用:是為了避免,自己自定義的模組入口出口函式名,與未知的函式名重名,而帶來的重新定義的問題, 函式可以加上 static 關鍵字修飾,經過 static 關鍵字修飾過的函式的連結屬性為內部,從而解決了該問題
6、測試:
安裝 insmod xxx.ko
檢視 lsmod
解除安裝 rmmod xxx
7、Makefile編寫
KERNELDIR = /lib/modules/$(shell uname -r)/build/
#ubuntu核心的路徑
#KERNELDIR = /home/liu/Linux/kernel-3.4.39/
#開發板核心的路徑
PWD=$(shell pwd)
#當前路徑
NAME ?= demo.c
#需要編譯的模組名字
NAMES := $(patsubst %.c,%,$(NAME))
#擷取字串 xx.c 裡的 .c 之前的內容
obj-m:=$(NAMES).o
#需要的依賴檔案
all:
make -C $(KERNELDIR) M=$(PWD) modules
@# mkae -C $(KERNELDIR)
@# 進入核心頂層目錄下,讀取目錄下的Makefile檔案,並執行這個Makefile檔案
@# M=$(PWD) 指定編譯模組的路徑
@# modules 編譯模組的選項
@# 如:
@# 1、cd $(KERNELDIR)
@# 2、mkae M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
@# mkae -C $(KERNELDIR)
@# 進入核心頂層目錄下,讀取目錄下的Makefile檔案,並執行這個Makefile檔案
@# M=$(PWD) 指定編譯模組的路徑
@# clean 清除的選項
@# 如:
@# 1、cd $(KERNELDIR)
@# 2、make M=$(PWD) clean
cp:
cp $(NAMES).ko ~/nfs/rootfs/