linux字元裝置驅動程式scull例項
這個例子還是比較完整的講述了字元驅動開發的過程,尤其字元驅動程式的設計流程,包括測試在內。
【1.系統環境】
該驅動程式在UBUNTU10.04LTS編譯通過,系統核心為linux-2.6.32-24(可使用uname -r 命令來檢視當前核心的版本號)
由於安裝UBUNTU10.04LTS時,沒有安裝LINUX核心原始碼,因此需要在www.kernel.org下載LINUX原始碼,下載linux-2.6.32.22.tar.bz2(與系統執行的LINUX核心版本儘量保持一致),使用如下命令安裝核心:
1.解壓核心
|
2.為系統的include建立連結檔案
|
LINUX核心原始碼安裝完畢
【2.驅動程式程式碼】
|
|
【3.編譯驅動程式模組】
Makefile檔案的內容如下:
|
切換到root下,執行make時,如果UBUNTU是使用虛擬機器安裝的,那麼執行make時,不要在ubuntu和windows的共享目錄下,否則會出錯。
/root/memdev.o /root/memdev.ko |
ls檢視當前目錄的內容
|
這裡的memdev.ko就是生成的驅動程式模組。
通過insmod命令把該模組插入到核心
|
檢視插入的memdev.ko驅動
|
可以看到memdev驅動程式被正確的插入到核心當中,主裝置號為260,該裝置號為memdev.h中定義的#define MEMDEV_MAJOR 260。
如果這裡定義的主裝置號與系統正在使用的主裝置號衝突,比如主裝置號定義如下:#define MEMDEV_MAJOR 254,那麼在執行insmod命令時,就會出現如下的錯誤:
|
檢視當前裝置使用的主裝置號
|
發現字元裝置的254主裝置號為rtc所使用,因此會出現上述錯誤,解決方法只需要在memdev.h中修改主裝置號的定義即可。
【4.編寫應用程式,測試該驅動程式】
首先應該在/dev/目錄下建立與該驅動程式相對應的檔案節點,使用如下命令建立:
|
使用ls檢視建立好的驅動程式節點檔案
|
編寫如下應用程式,來對驅動程式進行測試。
|
編譯並執行該程式
|
表明驅動程式工作正常。。。
【5.LINUX是如何make驅動程式模組的】
Linux核心是一種單體核心,但是通過動態載入模組的方式,使它的開發非常靈活 方便。那麼,它是如何編譯核心的呢?我們可以通過分析它的Makefile入手。以下是 一個簡單的hello核心模組的Makefile.
ifneq ($(KERNELRELEASE),)
obj-m:=hello.o
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.mod.o *.ko
endif
當我們寫完一個hello模組,只要使用以上的makefile。然後make一下就行。 假設我們把hello模組的原始碼放在/home/study/prog/mod/hello/下。 當我們在這個目錄執行make時,make是怎麼執行的呢? LDD3第二章第四節“編譯和裝載”中只是簡略地說到該Makefile被執行了兩次, 但是具體過程是如何的呢?
首先,由於make 後面沒有目標,所以make會在Makefile中的第一個不是以.開頭 的目標作為預設的目標執行。於是default成為make的目標。make會執行 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules shell是make內部的函式,假設當前核心版本是2.6.13-study,所以$(shell uname -r)的結果是 2.6.13-study 這裡,實際執行的是
make -C /lib/modules/2.6.13-study/build M=/home/study/prog/mod/hello/ modules
/lib/modules/2.6.13-study/build是一個指向核心原始碼/usr/src/linux的符號連結。 可見,make執行了兩次。第一次執行時是讀hello模組的原始碼所在目錄/home/s tudy/prog/mod/hello/下的Makefile。第二次執行時是執行/usr/src/linux/下的Makefile時.
但是還是有不少令人困惑的問題: 1.這個KERNELRELEASE也很令人困惑,它是什麼呢?在/home/study/prog/mod/he llo/Makefile中是沒有定義這個變數的,所以起作用的是else…endif這一段。不 過,如果把hello模組移動到核心原始碼中。例如放到/usr/src/linux/driver/中, KERNELRELEASE就有定義了。 在/usr/src/linux/Makefile中有 162 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
這時候,hello模組也不再是單獨用make編譯,而是在核心中用make modules進行 編譯。 用這種方式,該Makefile在單獨編譯和作為核心一部分編譯時都能正常工作。
2.這個obj-m := hello.o什麼時候會執行到呢? 在執行:
make -C /lib/modules/2.6.13-study/build M=/home/study/prog/mod/hello/ modules
時,make 去/usr/src/linux/Makefile中尋找目標modules: 862 .PHONY: modules 863 modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) 864 @echo ' Building modules, stage 2.'; 865 $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
可以看出,分兩個stage: 1.編譯出hello.o檔案。 2.生成hello.mod.o hello.ko 在這過程中,會呼叫 make -f scripts/Makefile.build obj=/home/study/prog/mod/hello 而在 scripts/Makefile.build會包含很多檔案: 011 -include .config 012 013 include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)
其中就有/home/study/prog/mod/hello/Makefile 這時 KERNELRELEASE已經存在。 所以執行的是: obj-m:=hello.o
關於make modules的更詳細的過程可以在scripts/Makefile.modpost檔案的註釋 中找到。如果想檢視make的整個執行過程,可以執行make -n。
相關推薦
linux字元裝置驅動程式scull例項
這個例子還是比較完整的講述了字元驅動開發的過程,尤其字元驅動程式的設計流程,包括測試在內。 【1.系統環境】 該驅動程式在UBUNTU10.04LTS編譯通過,系統核心為linux-2.6.32-24(可使用uname -r 命令來檢視當前核心的版本號) 由於安裝UBUNTU10.04LTS時,沒有安裝LI
從零開始寫linux字元裝置驅動程式(一)(基於友善之臂tiny4412開發板)
從這篇博文開始,我將開始手把手教會大家寫linux裝置驅動程式這是開篇,如何來寫第一個字元裝置驅動程式。首先,寫一個最簡單的字元裝置驅動程式需要什麼?或者說我們需要了解什麼?1、每一個字元裝置至少需要有一個裝置號2、裝置號 = 主裝置號 + 次裝置號3、同一類裝置的主裝置號一
Linux字元裝置驅動程式的一個簡單示例
一.原始碼: // memdev.c #define MEMDEV_MAJOR 254 /*預設的mem的主裝置號*/ #define MEMDEV_NR_DEVS 2 /*裝置數*/ #define MEMDEV_SIZE 4096 /*mem裝置描述結構體
韋東山嵌入式Linux學習筆記之——第12課第8節 字元裝置驅動程式之定時器防抖動
注:本文部分內容摘自《魚樹學員筆記》。 當按鍵按得比較快的時候,這裡出現了兩次中斷值,也即產生了抖動。 這裡產生了“抖動”,按鍵是機械開關,按下鬆開時裡面的金屬彈片可能抖動了好幾次。這種抖動產生了多次“脈衝”導致多次中斷。 方法: 使用定時器來防抖動。
字元裝置驅動程式的三種寫法
驅動工程師如何去寫驅動程式? 要看原理圖。確定如何去操作硬體。 對於點亮led燈來說,確定引腳,檢視晶片手冊,確定如何去操作引腳,要設定哪些暫存器,如何設定這些暫存器才可以讓這個引腳輸出高電平或者低電平。 寫驅動程式 驅動程式起封裝作用,如何封裝。應用程式要操作硬體需要o
字元裝置驅動程式之非同步通知
非同步通知: 驅動程式的所謂非同步通知,指的是應用程式不是主動對驅動程式進行操作,而是驅動程式查詢到有事件發生或者有資料發生變化的時候通知應用程式。角色發生了變化,應用程式由主動改為被動執行。 比如按鍵驅動: 1、要不斷進行查詢引腳狀
Linux字元裝置驅動模型--字元裝置的註冊
當我們編寫字元裝置驅動程式的時候,在進行字元裝置物件cdev的分配、初始化,裝置號的註冊這些初始化階段之後,就可以將它加入到系統中,這樣才能使用這個字元裝置。將一個字元裝置加入到系統中呼叫的函式時cdev_add,核心原始碼如下: int cdev_add(struct cdev *
Linux 字元裝置驅動結構(二)—— 自動建立裝置節點
上一篇我們介紹到建立裝置檔案的方法,利用cat /proc/devices檢視申請到的裝置名,裝置號。 第一種是使用mknod手工建立:mknod filename type major minor 第二種是自動建立裝置節點:利用u
Linux 字元裝置驅動結構(一)—— cdev 結構體、裝置號相關知識解析
一、字元裝置基礎知識 1、裝置驅動分類 linux系統將裝置分為3類:字元裝置、塊裝置、網路裝置。使用驅動程式: 字元裝置:是指只能一個位元組一個位元組讀寫的裝置,不能隨機讀取裝置記憶體中的某一資料,讀取資料需要按照先後資料。
Linux字元裝置驅動註冊三種方法以及核心分析
Linux驅動是使用者訪問底層硬體的橋樑,驅動有可以簡單分成三類:字元裝置、塊裝置、網路裝置。其中最多的是字元裝置,其中字元裝置的註冊方法主要有三種:雜項設備註冊、早期字元設備註冊、標準字元設備註冊。以及詳細介紹各類方法註冊。 開發環境: PC:WMwork
淺析字元裝置驅動程式__register_chrdev_region
在 2.4 的核心我們使用 register_chrdev(0, “hello”, &hello_fops) 來進行字元裝置裝置節點的分配,這種方式每一個主裝置號只能存放一種裝置,它們使用相同的 file_operation 結構體,也就是說核心最多支
linux字元裝置驅動模型
一.雜項裝置驅動模型 雜項的主裝置號固定為10,只有255個次裝置號。可以直接生成驅動核心。 1.需要確定每個模型都會用到的檔案操作方法集合指標 2.確定核心的結構體 static struct miscdevice abc 確定三個引數,第一個為次裝置號,第二個是次裝
Linux字元裝置驅動
一、字元裝置基礎 字元裝置:是指只能一個位元組一個位元組進行讀寫操作的裝置,不能隨機讀取裝置中的某一資料、讀取資料要按照先後資料。字元裝置是面向流的裝置,常見的字元裝置有滑鼠、鍵盤、串列埠、控制檯和LED等。 一般每個字元裝置或者塊裝置都會在/dev目錄(可以是任意目錄,這樣是為了統一)下對應一個裝置檔案
linux塊裝置驅動程式示例(適用於高版本核心3.16.0
1. 字元裝置與塊裝置的 I/O 操作主要有如下不同點: (1)塊裝置只能以塊為單位接受輸入和返回輸出,而字元裝置則以位元組為單位。大多數裝置是字元裝置,因為它們不需要緩衝而且不以固定塊大小進行操作。 (2)塊裝置對於 I/O 請求有對應的緩衝區,因此它們可以選擇
1--linux字元裝置驅動
1. 編寫一個簡單的字元裝置框架 *****hello.c***** #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <
Linux 字元裝置驅動結構(三)—— file、inode結構體及chardevs陣列等相關知識解析
先看下面這張圖,這是Linux 中虛擬檔案系統、一般的裝置檔案與裝置驅動程式值間的函式呼叫關係; 上面這張圖展現了一個應用程式呼叫字元裝置驅動的過程, 在裝置驅動程式的設計中,一般而言,會關心 file 和 inode 這兩個結構體
字元裝置驅動程式——定時器按鍵消抖
實現方式 需要設定的結構體 struct timer_list { struct list_head entry; unsigned long expires; void (*function)(unsigned long); unsigned long data; struct tvec_
字元裝置驅動程式——按鍵中斷之互斥阻塞操作
一、互斥操作 在程式設計中,引入了物件互斥鎖的概念,來保證共享資料操作的完整性。每個物件都對應於一個可稱為" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有一個執行緒訪問該物件。 實現方式 原子操作 原子操作指的是在執行過程中不會被別的程式碼路徑所中斷的操作。 常用
字元裝置驅動程式——按鍵中斷之非同步通知
一、驅動程式的實現 1、定義static struct fasync_struct *newdrv_async; 2、加入 static struct file_operations new_drv_fops = { .fasync =new_drv_fasync, }; static
字元裝置驅動程式——按鍵中斷poll機制
編譯環境 ubunt 16.04 arm-linux-gcc 4.3.2 linux-3.4.2 zj2440 poll的作用是把當前的檔案指標掛到等待佇列。 對於一個按鍵事件: 1、查詢方法:在while(1)中不斷迴圈呼叫read(fd, &key_val, 1)查詢,不