Linux內核——字符設備.
- 設備相關點解
- 簡述字符設備驅動的設計流程
- 編寫對應Makefile
1 2 3 4 5 6 7 8 9 10
obj-m += led_dev.o KERNEL_DIR := /home/bbigq/6818GEC/kernel CROSS_COMPILE := /home/bbigq/6818GEC/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- PWD := $(shell pwd) default: $(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL_DIR) M=$(PWD) modules clean: rm *.o *.order .*.cmd *.mod.c *.symvers .tmp_versions -rf
設備相關點解.
Linux驅動設備一共分爲三種:字符設備
、塊設備
、網絡設備
,其中只有網絡設備比較特殊,其在/dev
目錄下是沒有設備文件的。
區分文件類型:
符號 | 文件類型 |
---|---|
c | 字符設備 |
b | 塊設備 |
d | 目錄 |
l | 符號鏈接 |
字符設備
該設備對數據的處理按照字節流
的形式進行的,支持順序訪問(是有時間的概念),也可以支持隨機訪問。典型
的字符設備:串口、鍵盤、觸摸屏、攝像頭、I2C、SPI、聲卡、幀緩衝設備….順序
訪問的設備:串口、鍵盤、觸摸屏隨機
訪問的設備:幀緩衝設備
應用程序,能夠使用系統IO函數來就行訪問:open、write、read、lseek、close…..
比如在根目錄的/dev
下我們能看到
其中第五第六列分別是主設備號
和次設備號
如:fb0的主設備號爲29,次設備號爲0
|
|
主設備號
主設備號主要用於區分某一類型的設備,比如顯示器、鼠標、鍵盤、硬盤等
次設備號
次設備號用來區分同一類型設備的不同個體或者不同分區,比如顯示器A.a、顯示器A.b 或者硬盤的分區1~分區7;
簡述字符設備驅動的設計流程.
- 首先定義一個字符設備
struct cdev
- 申請設備號
a. 靜態註冊
b. 動態註冊MKDEV register_chrdev_region
alloc_chrdev_region
- 定義
file_operations
,初始化打開、關閉、讀、寫等函數接口。 - cdev初始化
.cdev_init - 將cdev加入到內核
.cdev_add - 創建設備文件
.手動創建,去/dev目錄進行創建
.自動創建
1)class_create
2)device_create
此處默認都能使用Source Insight來閱讀內核源碼了
定義一個字符設備.
使用到一個結構體,見include/linux/cdev.h –> cdev
|
|
kobj
:內核管理驅動的時候,自動管理的對象,自動鏈接調用(不需要我們管);*owner
:屬於哪一個內核模塊,初始化一般默認編寫值爲THIS_MODULE,指向當前模塊;(重點)*ops
:字符設備文件操作集;(重點)list
:內核自動管理字符設備的鏈表,內核自動調用;dev
:設備號;count
:對當前設備申請次設備號的數目;(重點)
定義並初始化一個文件操作集.
定義一個file_operations
結構體,見/include/linux/fs.h –> file_operations
|
|
當然很多時候我們用不到它結構體定義的這麼多函數接口,只需保留最常用的即可;
每個字符設備都必須有一個文件操作集,文件操作集是驅動程序給應用程序訪問硬件的一個接口
,應用層與驅動程序函數接口的對應關係如下:
應用層 | 驅動層 |
---|---|
open | open |
close | release |
write | write |
read | read |
lseek | llseek |
ioctl | unlocked_ioctl |
用法例子:(摘自源碼bsg.c)
|
|
對應的:
|
|
當應用層的
open函數
調用了xxx.ko
的xxx_open
函數
當應用層的write函數
調用了xxx.ko
的xxx_write
函數
當應用層的close函數
調用了xxx.ko
的xxx_release
函數
…
我們需要定義一個file_operations
的結構體把自己編寫的接口配置進去,以便後續cdev_init
的初始化。
源碼及詳解.
led_dev.c
|
|
要點詳解
靜態申請設備號 MKDEV
MKDEV
原型 參數1:主設備號,參數2:次設備號
|
|
註冊設備號
register_chrdev_region
原型 參數1:聲明的設備號,參數2:註冊的數量,參數3:註冊的名字 返回值:成功爲0,失敗返回負數的錯誤碼
|
|
字符設備的初始化
cdev_init
原型 參數1:定義的字符設備,參數2:file_operations
|
|
將設備加入內核
cdev_add
原型 參數1:定義的字符設備地址,參數2:聲明的設備號,參數3:加入的數量,返回值:成功爲0,失敗爲負數錯誤值
|
|
設備號註銷
unregister_chrdev_region
原型 參數1:聲明的設備號,參數2:數量
|
|
將字符設備從內核刪除
cdev_del
原型 參數1:定義的字符設備地址
|
|
編寫對應Makefile.
|
|
編譯完成後,insmod
到Linux系統中後,可以通過lsmod
查看相關信息,也可以使用cat命令查看/proc/devices
,能夠找到註冊成功的設備名字。
注意:由於沒有這裏只是小demo是需要手動創建設備節點的,如果配合應用程序使用時,需要爲該設備在/dev
目錄下創建設備文件;
使用:
mknod /dev/led c 239 0
mknod 設備文件 設備類型 主設備號 次設備號
後續的博客中將會加入自動創建設備節點的代碼,和講解!
注意
1.手動創建設備文件的時候,主設備號和次設備號不能寫錯;
2.若此前的設備文件已經存在,再次創建相同名字的設備文件,會出現錯誤;(解決方法:先使用rm命令刪除原來的設備文件,再使用mknod命令重新創建。
)
最後用ls -l /dev/xxx
檢查是否創建成功!