生活随笔
收集整理的這篇文章主要介紹了
Linux驱动编程 step-by-step (一)驱动程序的作用
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
驅(qū)動(dòng)程序的作用:
簡(jiǎn)單來(lái)說(shuō) 驅(qū)動(dòng)程序就是使計(jì)算機(jī)與設(shè)備通信的特殊的代碼,在作單片機(jī)時(shí)候(無(wú)OS)我們自己定義接口及自定義的結(jié)構(gòu)來(lái)操作相關(guān)硬件,而在有OS的模式下我們操作的硬件是去實(shí)現(xiàn)對(duì)應(yīng)的接口(這些接口是已定義好的,我們需要實(shí)現(xiàn)這些接口)而無(wú)需自己定義接口,這樣既能正確的控制設(shè)備。又能很好的維護(hù)(如果需要升級(jí)驅(qū)動(dòng),上邊的應(yīng)用程序不需要改變)
編寫(xiě)驅(qū)動(dòng)考慮的因素
提供給用戶更多的選項(xiàng) 保持用戶操作的簡(jiǎn)單性 編寫(xiě)驅(qū)動(dòng)的時(shí)間
驅(qū)動(dòng)分類:
字符設(shè)備:能夠像字節(jié)流(類似文件)一樣被訪問(wèn)的設(shè)備(至少實(shí)現(xiàn)open, close, read ,write等功能) 快設(shè)備:??? 用戶空間接口與字符設(shè)備相同, 內(nèi)部實(shí)與字符設(shè)備完全不同(可以被隨即訪問(wèn),一般在類UNIX系統(tǒng)中快設(shè)備的讀取每次只能讀一整塊在linux可以操作任意字節(jié)) 網(wǎng)絡(luò)設(shè)備:網(wǎng)絡(luò)通路通過(guò)網(wǎng)絡(luò)設(shè)備形成,能夠與主機(jī)交換數(shù)據(jù)的設(shè)備
內(nèi)核功能劃分:
進(jìn)程管理(PM):進(jìn)程的創(chuàng)建與撤銷,在單個(gè)或者多個(gè)CPU上實(shí)現(xiàn)多進(jìn)程的抽象 內(nèi)存管理(MM):管理內(nèi)存分配及回收的策略 文件系統(tǒng)(FS/VFS): Linux 非常依賴于文件系統(tǒng),內(nèi)核在沒(méi)有結(jié)構(gòu)的硬件系統(tǒng)上構(gòu)造結(jié)文件系統(tǒng),而文件抽象在整個(gè)系統(tǒng)中會(huì)廣泛使用,Linux支持多種文件系統(tǒng)類型 設(shè)備控制:驅(qū)動(dòng)程序,操控硬件以及相應(yīng)總線設(shè)備 網(wǎng)絡(luò)(NET): 在網(wǎng)絡(luò)接口于應(yīng)用程序之間傳輸數(shù)據(jù)。
好了 理論行得東西介紹的差不多了,下邊說(shuō)點(diǎn)有用的,內(nèi)核的驅(qū)動(dòng)可以做成模塊在需要的時(shí)候裝載,在不需要的時(shí)候卸載 我們?cè)诰帉?xiě)用戶程序的時(shí)候總喜歡從編寫(xiě)hello world 寫(xiě)起 , 在內(nèi)核驅(qū)動(dòng)模塊也是一樣,下邊是一個(gè)hello_world的一個(gè)模塊
?? #include?<linux/init.h>? ?? #include?<linux/module.h> ?? MODULE_LICENSE( "GPL" ); ?? ?? static ? int ?hello_init( void ) ?? { ?? ????printk(KERN_ALERT? "hello?module\n" ); ?? ???? return ?0; ?? } ?? ?? static ? void ?hello_exit( void ) ?? { ?? ????printk(KERN_ALERT? "hello?module?exit\n" ); ?? } ?? ?? module_init(hello_init); ?? module_exit(hello_exit);??
以及對(duì)應(yīng)的Makefile
ifneq?($(KERNELRELEASE),) ?? #?call?from?kernel?build?system? ?? obj-m???:=?hello_world.o ?? #if?we?need?more?than?one?source?code?to?build?the?module ?? #we?should?use?the?variable?below:??example:?modules-objs?:=?file1.o?file2.o ?? modules-objs?:= ?? ?? else ?? #kernel?PTAH? ?? KERNELDIR??=?/lib/modules/$(shell?uname?-r)/build ?? PWD???????:=?$(shell?pwd) ?? ?? modules: ?? ????$(MAKE)?-C?$(KERNELDIR)?M=$(PWD)?modules ?? ?? endif ?? ?? clean: ?? ????rm?-rf?*.o?*~?core?.depend?.*.cmd?*.ko?*.mod.c?.tmp_versions??
有幾點(diǎn)與用戶空間程序不同的地方
模塊程序沒(méi)有main函數(shù)(那么程序入口在哪里?) 打印函數(shù)使用的printk 而不是用戶空間的printf 而且使用方式不一樣 模塊的編譯不是通常的方式 頭文件不是常見(jiàn)的那些頭文件 以及編譯之后不會(huì)產(chǎn)生可執(zhí)行文件,而是 .ko 文件 ...
模塊沒(méi)有main函數(shù),在裝載模塊 insmod 時(shí)會(huì)調(diào)用module_init注冊(cè)的函數(shù) 此處為hello_init 在模塊卸載remod時(shí) 會(huì)調(diào)用module_exit注冊(cè)的函數(shù) 此處為hello_exit 在module_init 注冊(cè)的函數(shù)主要是進(jìn)行初始化,分配內(nèi)存, 注冊(cè)設(shè)備等 而module_exit中注冊(cè)的函數(shù)與之相反, 設(shè)備注銷, 釋放內(nèi)存等 具體的編譯模塊的Makefile我在另一篇文章中有說(shuō)到 此處不再贅述 內(nèi)核的打印函數(shù)使用printk去打印信息, printk不支持浮點(diǎn)類型, 在printk中可以加入信息級(jí)別有7中
#define?KERN_EMERG????"<0>"????/*?system?is?unusable?*/ ?? #define?KERN_ALERT????"<1>"????/*?action?must?be?taken?immediately?*/ ?? #define?KERN_CRIT?????"<2>"????/*?critical?conditions?*/ ?? #define?KERN_ERR??????"<3>"????/*?error?conditions?*/ ?? #define?KERN_WARNING??"<4>"????/*?warning?conditions?*/ ?? #define?KERN_NOTICE???"<5>"????/*?normal?but?significant?*/ ?? #define?KERN_INFO?????"<6>"????/*?informational?*/ ?? #define?KERN_DEBUG????"<7>"????/*?debug-level?messages?*/ ??
對(duì)應(yīng)與不同的錯(cuò)誤等級(jí) 選擇不懂的option, 并做不同的處理, 小于一定等級(jí)的信息會(huì)直接打印到終端(非X-window下的終端),可以使用
dmesg
來(lái)查看全部的打印信息
編譯內(nèi)核的頭文件是在/lib/modules/$(shell?uname?-r)/build/include下得,而不是用戶模式下得/usr/include
編譯后不會(huì)生產(chǎn)可執(zhí)行文件,會(huì)生成一個(gè).ko的文件
使用
insmod?
xxx
.ko去裝載模塊
使用
lsmod
去查看已裝載的模塊
使用
rmmod?
xxx?
去卸載相應(yīng)模塊(卸載是不帶.ko)
總結(jié)
以上是生活随笔 為你收集整理的Linux驱动编程 step-by-step (一)驱动程序的作用 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。