Linux字符设备驱动实例
globalmem
看 linux 設(shè)備驅(qū)動(dòng)開發(fā)詳解時(shí),字符設(shè)備驅(qū)動(dòng)一章,寫的測(cè)試代碼和應(yīng)用程序,加上自己的操作,對(duì)初學(xué)者我覺得非常有幫助。
寫這篇文章的原因是因?yàn)槲铱戳宋抑鞍l(fā)表的文章,還沒有寫過字符設(shè)備相關(guān)的,至于里面提到的結(jié)構(gòu)體的作用,有很多詳細(xì)的文章說明,我就不做更深的敘述。
代碼在github上,點(diǎn)擊下面閱讀原文可以直達(dá)
https://github.com/weiqifa0/globalmem/blob/main/README.md
把這部分放在github上也有好處,后續(xù)可以增加刪除一些東西,以后自己需要使用的時(shí)候也方便許多。
我們討論字符設(shè)備驅(qū)動(dòng),就有必要知道他的結(jié)構(gòu)體和頭文件,像一些后來的封裝什么的,大部分還是脫離不了操作這個(gè)結(jié)構(gòu)體里面的東西。
/*?SPDX-License-Identifier:?GPL-2.0?*/ #ifndef?_LINUX_CDEV_H #define?_LINUX_CDEV_H#include?<linux/kobject.h> #include?<linux/kdev_t.h> #include?<linux/list.h> #include?<linux/device.h>struct?file_operations; struct?inode; struct?module;struct?cdev?{struct?kobject?kobj; /*內(nèi)嵌kobject結(jié)構(gòu)體,方便以后應(yīng)用,也會(huì)在sys下生成相關(guān)設(shè)備文件*/struct?module?*owner;/*所屬于的模塊,正常就是本模塊THIS_MODULE*/const?struct?file_operations?*ops;/*文件的操作結(jié)構(gòu)體,設(shè)備也是一個(gè)文件*/struct?list_head?list;/*字符設(shè)備的鏈表頭*/dev_t?dev;/*設(shè)備號(hào)*/unsigned?int?count; }?__randomize_layout; /*初始化cdev,并建立和file_operation的聯(lián)系*/ void?cdev_init(struct?cdev?*,?const?struct?file_operations?*); /*申請(qǐng)cdev內(nèi)存*/ struct?cdev?*cdev_alloc(void);void?cdev_put(struct?cdev?*p);int?cdev_add(struct?cdev?*,?dev_t,?unsigned);void?cdev_set_parent(struct?cdev?*p,?struct?kobject?*kobj); int?cdev_device_add(struct?cdev?*cdev,?struct?device?*dev); void?cdev_device_del(struct?cdev?*cdev,?struct?device?*dev);void?cdev_del(struct?cdev?*);void?cd_forget(struct?inode?*);#endif加載內(nèi)核模塊insmod globalmem.ko 錯(cuò)誤需要的修改。
insmod: can't insert 'globalmem.ko': Device or resource busy
出錯(cuò)的原因:
模塊使用的是靜態(tài)分配設(shè)備號(hào)的方式,而這個(gè)設(shè)備號(hào)已經(jīng)被系統(tǒng)中的其他設(shè)備所占用。查看未被占用的設(shè)備號(hào),需要到pro/devices下面去查看。
查看設(shè)備號(hào)的方法:
# cat /proc/devices
編譯內(nèi)核版本
#uname?-a
Linux?bsp-ubuntu1804?4.15.0-117-generic?#118-Ubuntu?SMP?Fri?Sep?4?20:02:41?UTC?2020?x86_64?x86_64?x86_64?GNU/Linux加載模塊之后使用lsmod查看模塊
weiqifa@bsp-ubuntu1804:~/c/globalmem$?sudo?insmod?globalmem.koweiqifa@bsp-ubuntu1804:~/c/globalmem$?lsmod?|grep?global globalmem??????????????16384??0 weiqifa@bsp-ubuntu1804:~/c/globalmem$weiqifa@bsp-ubuntu1804:~/c/globalmem$?cat?/proc/devices?|grep?global 230?globalmem weiqifa@bsp-ubuntu1804:~/c/globalmem$創(chuàng)建設(shè)備文件節(jié)點(diǎn)
使用mknod創(chuàng)建設(shè)備節(jié)點(diǎn)的時(shí)候,后面跟上的參數(shù)需要跟我們?cè)?proc/devices下面看到的對(duì)應(yīng),也就是我們?cè)隍?qū)動(dòng)里面申請(qǐng)的主設(shè)備號(hào)。
weiqifa@bsp-ubuntu1804:~/c/globalmem$?sudo?mknod?/dev/globalmem?c?230?0 weiqifa@bsp-ubuntu1804:~/c/globalmem$?ls?/dev/globalmem?-al crw-r--r--?1?root?root?230,?0?Dec?22?16:19?/dev/globalmem weiqifa@bsp-ubuntu1804:~/c/globalmem$使用命令讀寫設(shè)備文件
Linux 下的 echo 和cat 命令是十分有用,這兩個(gè)命令可以讓在不寫代碼的情況下就可以完成調(diào)試讀寫設(shè)備。
通過代碼來讀寫設(shè)備文件
代碼在下面閱讀原文的鏈接里面。
使用傳入?yún)?shù)設(shè)置主設(shè)備號(hào)
內(nèi)核模塊參數(shù)我覺得是一個(gè)比較冷門的知識(shí)點(diǎn),冷門的原因是因?yàn)槲覀冊(cè)谧鲰?xiàng)目的時(shí)候很少使用這個(gè)參數(shù),但是實(shí)際上這個(gè)參數(shù)非常有用。
我們可以把內(nèi)核模塊當(dāng)做main函數(shù),main函數(shù)是可以接收傳參的,內(nèi)核模塊也可以在加載的時(shí)候接收傳入的參數(shù)。
如下是把主設(shè)備號(hào)傳給內(nèi)核模塊,但是需要注意,這個(gè)主設(shè)備號(hào)不能被占用了。
weiqifa@bsp-ubuntu1804:~/c/globalmem$?sudo?insmod?globalmem.ko?globalmem_major=231 weiqifa@bsp-ubuntu1804:~/c/globalmem$?cat?/proc/devices?|grep?globalmem 231?globalmem weiqifa@bsp-ubuntu1804:~/c/globalmem$增加自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)的驅(qū)動(dòng)文件
每次手動(dòng)創(chuàng)建設(shè)備文件節(jié)點(diǎn)總是很麻煩,而且在實(shí)際編寫設(shè)備驅(qū)動(dòng)的時(shí)候,不會(huì)出現(xiàn)自己手動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)這種低端的操作。
當(dāng)然了,聰明的內(nèi)核提供了接口讓我們?cè)谧?cè)驅(qū)動(dòng)的時(shí)候也把設(shè)備文件節(jié)點(diǎn)注冊(cè)上去。
具體代碼可以查看globalmem2.c里面的代碼。
使用lseek操作文件位置
具體對(duì)應(yīng)的文件是app-main2.c
推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
我的知識(shí)小密圈
總結(jié)
以上是生活随笔為你收集整理的Linux字符设备驱动实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 下周开幕!给深圳的嵌入式和电子工程师准备
- 下一篇: 浪潮财务软件遇到问题