Linux中很多設(shè)備都是字符設(shè)備,使用ls -l查看/dev下的設(shè)備,前面帶c的都是字符設(shè)備。
字符設(shè)備的創(chuàng)建比較容易,而且有一套固定的模式,掌握了模式完全可以“套模板”。更多的精力應(yīng)該花在業(yè)務(wù)邏輯的部分。
Linux的每個(gè)設(shè)備都有一個(gè)主設(shè)備號和次設(shè)備號,創(chuàng)建字符設(shè)備第一步就是給它分配設(shè)備號。如果是自己用,可以任意給定一個(gè)沒有用過的設(shè)備號,也可以讓系統(tǒng)自動(dòng)分配。但是如果要發(fā)布給不同的人不同的機(jī)器使用,就不能隨便。推薦使用系統(tǒng)自動(dòng)分配的方式。
下面代碼中根據(jù)有沒有給定設(shè)備號決定是指定還是自動(dòng)分配設(shè)備號,dev變量里包含了主設(shè)備號和次設(shè)備號。MKDEV就是將兩個(gè)數(shù)字合成的。register_chrdev_region()函數(shù)注冊字符設(shè)備,alloc_chrdev_region()函數(shù)自動(dòng)分配設(shè)備號。主設(shè)備號是關(guān)鍵,次設(shè)備號可以看成是該類設(shè)備的計(jì)數(shù)。通過MAJOR()可以得到主設(shè)備號。
字符設(shè)備一般會(huì)創(chuàng)建一個(gè)數(shù)據(jù)結(jié)構(gòu),里邊包含了cdev結(jié)構(gòu)、設(shè)備數(shù)據(jù)和其他數(shù)據(jù),可以根據(jù)自己實(shí)際需求添加。然后創(chuàng)建該結(jié)構(gòu)的指針。
分配完設(shè)備號,接下來給字符設(shè)備數(shù)據(jù)結(jié)構(gòu)分配存儲(chǔ)空間。
創(chuàng)建設(shè)備類
初始化字符設(shè)備、添加字符設(shè)備到內(nèi)核和創(chuàng)建設(shè)備。
這里涉及到一個(gè)結(jié)構(gòu)file_operations,這個(gè)結(jié)構(gòu)里包含了文件操作函數(shù)列表,所有操作這個(gè)字符設(shè)備的動(dòng)作函數(shù)地址都保存在這個(gè)結(jié)構(gòu)里。
結(jié)構(gòu)的定義在頭文件fs.h中,這個(gè)結(jié)構(gòu)有很多內(nèi)容,不過常用的就那么幾個(gè)。
如果沒遇到問題,到這里字符設(shè)備就創(chuàng)建成功了。如果失敗,就會(huì)goto到錯(cuò)誤處理的地方,這里用goto是因?yàn)槭『笠亚懊婵赡苌暾埖馁Y源釋放掉,而且有順序,這里一定要注意。
在exit函數(shù)中要有對應(yīng)的注銷或釋放資源的操作,順序跟創(chuàng)建時(shí)相反,后創(chuàng)建的先釋放,先創(chuàng)建的后釋放。
下面要完成的工作就是實(shí)現(xiàn)file_operations結(jié)構(gòu)中的函數(shù)。對于簡單的字符設(shè)備,最常見的操作是open、read、write、ioctl、release等。
open函數(shù)這里只是簡單的獲取了一下字符數(shù)據(jù)結(jié)構(gòu)體的指針。container_of函數(shù)很有意思,可以根據(jù)結(jié)構(gòu)成員的地址找到結(jié)構(gòu)體數(shù)據(jù)的地址。
read函數(shù)要實(shí)現(xiàn)將內(nèi)核空間的數(shù)據(jù)傳到用戶空間的功能,copy_to_user()函數(shù)就是干這個(gè)的,第一個(gè)和第三個(gè)參數(shù)就是read函數(shù)的形參,中間是內(nèi)核的數(shù)據(jù)。這里的count是字節(jié)個(gè)數(shù)。
write函數(shù)實(shí)現(xiàn)的功能與read相反,使用copy_from_user()和memdup_user()函數(shù)可以實(shí)現(xiàn)。
ioctl函數(shù)實(shí)現(xiàn)一些設(shè)備獨(dú)有操作的函數(shù),i2c設(shè)備和spi設(shè)備就大量使用了ioctl。
release函數(shù)就是在設(shè)備文件關(guān)閉時(shí)需要做的操作。這里的關(guān)閉是指打開該文件的文件描述符個(gè)數(shù)為0了,如果不為0只會(huì)將計(jì)數(shù)減1而不會(huì)真正調(diào)用release函數(shù)。
具體的實(shí)例可以參看Linux源碼中i2c-dev.c中i2c設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)。
必要的頭文件:
編譯模塊并插入到內(nèi)核后,在/dev目錄下會(huì)創(chuàng)建對應(yīng)的設(shè)備文件。
在/sys/class下會(huì)創(chuàng)建對應(yīng)的設(shè)備類目錄。
ok,以上就是簡單的創(chuàng)建字符設(shè)備的過程,通過字符設(shè)備可以實(shí)現(xiàn)內(nèi)核與用戶空間的數(shù)據(jù)交換。學(xué)習(xí)字符設(shè)備的創(chuàng)建也是學(xué)習(xí)linux驅(qū)動(dòng)開發(fā)的第一步。
-
存儲(chǔ)
+關(guān)注
關(guān)注
13文章
4169瀏覽量
85481 -
Linux
+關(guān)注
關(guān)注
87文章
11161瀏覽量
208459 -
設(shè)備
+關(guān)注
關(guān)注
2文章
4413瀏覽量
70442 -
字符
+關(guān)注
關(guān)注
0文章
230瀏覽量
25142 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4256瀏覽量
62223
發(fā)布評論請先 登錄
相關(guān)推薦
評論