




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Linux字符設(shè)備驅(qū)動(dòng)程序第1頁(yè)Linux驅(qū)動(dòng)程序分類字符設(shè)備驅(qū)動(dòng):用于驅(qū)動(dòng)能夠像字節(jié)流(文獻(xiàn))同樣被訪問(wèn)設(shè)備。應(yīng)用程序一般能夠利用open、close、read、write等系統(tǒng)調(diào)用訪問(wèn)字符設(shè)備驅(qū)動(dòng)。塊設(shè)備驅(qū)動(dòng):塊設(shè)備和字符設(shè)備只在系統(tǒng)內(nèi)核內(nèi)部管理上有所區(qū)分。應(yīng)用程序?qū)τ谧址O(shè)備每一種I/O操作都會(huì)被內(nèi)核直接傳遞給對(duì)應(yīng)驅(qū)動(dòng)程序;而應(yīng)用程序?qū)τ趬K設(shè)備操作要通過(guò)虛擬文獻(xiàn)系統(tǒng)(VFS)和緩沖區(qū)管理系統(tǒng)間接地傳遞給驅(qū)動(dòng)程序處理。網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng):應(yīng)用程序必須利用套接字(socket)接口訪問(wèn)網(wǎng)絡(luò)設(shè)備。第2頁(yè)第3頁(yè)網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序第4頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造字符設(shè)備開(kāi)發(fā)基本步驟確定主設(shè)備號(hào)和次設(shè)備號(hào)實(shí)現(xiàn)字符驅(qū)動(dòng)程序?qū)崿F(xiàn)file_operations構(gòu)造體構(gòu)造字符設(shè)備構(gòu)造體cdev在模塊加載函數(shù)中注冊(cè)字符設(shè)備在模塊卸載函數(shù)中注銷字符設(shè)備創(chuàng)建設(shè)備文獻(xiàn)節(jié)點(diǎn)第5頁(yè)設(shè)備文獻(xiàn)與設(shè)備號(hào)為了體現(xiàn)“一切都是文獻(xiàn)”設(shè)計(jì)思想,linux將每個(gè)已安裝設(shè)備都表達(dá)為一種設(shè)備文獻(xiàn)。設(shè)備文獻(xiàn)一般位于/dev子目錄。對(duì)于字符設(shè)備,應(yīng)用程序能夠利用open、close、read、write等系統(tǒng)調(diào)用訪問(wèn)其設(shè)備文獻(xiàn),這些I/O操作都被直接傳遞給該設(shè)備文獻(xiàn)所對(duì)應(yīng)設(shè)備。每個(gè)設(shè)備文獻(xiàn)中都存放了該設(shè)備“主設(shè)備號(hào)”和“次設(shè)備號(hào)”。一般由同一種內(nèi)核模塊管理多種設(shè)備占用同一種主設(shè)備號(hào),詳細(xì)設(shè)備用次設(shè)備號(hào)標(biāo)識(shí)。用mknodfilenamecmajorminor命令創(chuàng)建設(shè)備文獻(xiàn)用rmfilename命令刪除設(shè)備文獻(xiàn)。注意刪除設(shè)備文獻(xiàn)并不會(huì)影響驅(qū)動(dòng)模塊。第6頁(yè)應(yīng)用程序如何訪問(wèn)設(shè)備fd1=open(“/dev/ttyS1”,O_RDWR);//阻塞fd2=open(“/dev/ttyS1”,O_RDWR|O_NONBLOCK);//非阻塞intread(intfd,constvoid*buf,size_tlength);intwrite(intfd,constvoid*buf,size_tlength);intlseek(intfd,offset_toffset,intwhence);intioctl(intfd,intcmd,void*arg);intclose(intfd);第7頁(yè)設(shè)備號(hào)內(nèi)部體現(xiàn)設(shè)備編號(hào)內(nèi)部體現(xiàn)dev_t類型(32位):用來(lái)保存設(shè)備編號(hào)(包括主設(shè)備號(hào)(12位)和次設(shè)備號(hào)(20位))從dev_t取得主設(shè)備號(hào)和次設(shè)備號(hào):MAJOR(dev_t);MINOR(dev_t);將主設(shè)備號(hào)和次設(shè)備號(hào)轉(zhuǎn)換成dev_t類型:MKDEV(intmajor,intminor);
第8頁(yè)主設(shè)備號(hào)與次設(shè)備號(hào)分派主設(shè)備號(hào)手工分派主設(shè)備號(hào):找一種內(nèi)核沒(méi)有使用主設(shè)備號(hào)來(lái)使用。#include<linux/fs.h>intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name);要分派設(shè)備編號(hào)范圍起始值,次設(shè)備號(hào)經(jīng)常為0所祈求連續(xù)設(shè)備編號(hào)個(gè)數(shù)和該編號(hào)范圍關(guān)聯(lián)設(shè)備名稱第9頁(yè)主設(shè)備號(hào)與次設(shè)備號(hào)動(dòng)態(tài)分派主設(shè)備號(hào):#include<linux/fs.h>intalloc_chrdev_resion(dev_t*dev,unsignedintfirstminor,unsignedintcount,char*name);輸出設(shè)備號(hào)要使用被祈求第一種次設(shè)備號(hào)第10頁(yè)主設(shè)備號(hào)與次設(shè)備號(hào)釋放設(shè)備號(hào)voidunregister_chrdev_region(dev_tfirst,unsignedintcount);一般在模塊清除函數(shù)中調(diào)用。第11頁(yè)統(tǒng)計(jì)字符設(shè)備構(gòu)造體cdev實(shí)現(xiàn)字符驅(qū)動(dòng)程序cdev構(gòu)造體structcdev{ structkobjectkobj;/*內(nèi)嵌kobject對(duì)象*/ structmodule*owner;/*所屬模塊*/ structfile_operations*ops;/*文獻(xiàn)操作構(gòu)造體*/ structlist_headlist; dev_tdev;/*設(shè)備號(hào)*/ unsignedintcount;};cdevkobj、list、count字段不用我們關(guān)系和維護(hù)(內(nèi)核代勞),我們只需將其ops字段指向?yàn)槲覀冏约篺ileoperations構(gòu)造。第12頁(yè)對(duì)cdev構(gòu)造體操作操作cdev函數(shù)voidcdev_init(structcdev*,structfile_operations*);structcdev*cdev_alloc(void);intcdev_add(structcdev*,dev_t,unsigned);voidcdev_del(structcdev*);用于初始化cdev組員,并建立cdev和file_operations之間連接分別向系統(tǒng)刪除一種cdev,完成字符設(shè)備注銷,一般在模塊卸載函數(shù)中調(diào)用分別向系統(tǒng)添加一種cdev,完成字符設(shè)備注冊(cè),一般在模塊加載函數(shù)中調(diào)用函數(shù)用于動(dòng)態(tài)申請(qǐng)一種cdev內(nèi)存第13頁(yè)file_operations構(gòu)造體file_operations構(gòu)造體字符驅(qū)動(dòng)和內(nèi)核接口:在include/linux/fs.h定義字符驅(qū)動(dòng)只要實(shí)現(xiàn)一種file_operations構(gòu)造體并注冊(cè)到內(nèi)核中,內(nèi)核就有了操作此設(shè)備能力。structfile_operations{
structmodule*owner; loff_t(*llseek)(structfile*,loff_t,int); ssize_t(*read)(structfile*,char__user*,size_t,loff_t*); ssize_t(*write)(structfile*,const
char__user*,size_t,loff_t*);
unsigned
int(*poll)(structfile*,structpoll_table_struct*);
int(*ioctl)(structinode*,structfile*,unsigned
int,unsigned
long);
int(*open)(structinode*,structfile*);
int(*flush)(structfile*,fl_owner_tid);
int(*release)(structinode*,structfile*);//………};第14頁(yè)file_operations構(gòu)造體
file_operations主要組員:structmodule*owner:
指向模塊本身open:打開(kāi)設(shè)備release:關(guān)閉設(shè)備read:從設(shè)備上讀數(shù)據(jù)write:向設(shè)備上寫數(shù)據(jù)ioctl:I/O控制函數(shù)llseek:定位讀寫指針mmap:映射設(shè)備空間到進(jìn)程地址空間第15頁(yè)fileoperations初始化structfile_operationsmy_fops={.owner=THIS_MODULE,.llseek=my_llseek,.read=my_read,.write=my_write,.ioctl=my_ioctl,.open=my_open,.release=my_release,};第16頁(yè)file構(gòu)造體file構(gòu)造代表一種打開(kāi)文獻(xiàn),它由內(nèi)核在應(yīng)用程序open時(shí)創(chuàng)建,并將該文獻(xiàn)所對(duì)應(yīng)fileoperations統(tǒng)計(jì)在file構(gòu)造中。在應(yīng)用程序調(diào)用close函數(shù),內(nèi)核會(huì)釋放該數(shù)據(jù)構(gòu)造。structfile{ structfile_operations *f_op; unsignedint f_flags; fmode_t f_mode; loff_t f_pos;struct dentry *f_dentry void* private_data;};第17頁(yè)file構(gòu)造體file構(gòu)造體
file構(gòu)造:file_operations構(gòu)造有關(guān)一種構(gòu)造體。描述一種正在打開(kāi)設(shè)備文獻(xiàn)。組員:loff_tf_pos:
目前讀/寫位置unsignedintf_flags標(biāo)識(shí)文獻(xiàn)打開(kāi)時(shí),是否可讀或可寫O_RDONLYO_NONBLOCKO_SYNCstructfile_operations*f_op文獻(xiàn)有關(guān)操作,指向所實(shí)現(xiàn)structfile_operationsvoid*private_data:
私有數(shù)據(jù)指針。驅(qū)動(dòng)程序能夠?qū)⑦@個(gè)字段用于任何目標(biāo)或者忽視這個(gè)字段。第18頁(yè)inode構(gòu)造體內(nèi)核用inode構(gòu)造在內(nèi)部表達(dá)文獻(xiàn),用于存放文獻(xiàn)訪問(wèn)權(quán)限、屬主、組、大小、生產(chǎn)時(shí)間等VFS關(guān)懷信息。其字段中我們只關(guān)懷i_rdev(設(shè)備號(hào)),和i_cdev(和該文獻(xiàn)所對(duì)應(yīng)cdev構(gòu)造)我們?cè)趧?chuàng)建設(shè)備文獻(xiàn)時(shí),內(nèi)核會(huì)自動(dòng)創(chuàng)建一種對(duì)應(yīng)inode構(gòu)造體,并將其i_cdev字段指向?qū)?yīng)字符設(shè)備構(gòu)造體cdev(事先已經(jīng)在內(nèi)核中注冊(cè)過(guò))。Inode與file區(qū)分:file表達(dá)打開(kāi)文獻(xiàn)描述符,多種file構(gòu)造,能夠指向單個(gè)inode構(gòu)造。structinode{ dev_ti_rdev; structcdev*i_cdev; //………};第19頁(yè)Inode構(gòu)造體Inode構(gòu)造中兩個(gè)主要字段:dev_ti_rdev;對(duì)表達(dá)設(shè)備文獻(xiàn)inode構(gòu)造,該字段包括了真正設(shè)備編號(hào)。structcdev*i_cdev;structcdev是表達(dá)字符設(shè)備內(nèi)核內(nèi)部構(gòu)造。當(dāng)inode指向一種字符設(shè)備文獻(xiàn)時(shí),該字段包括了指向structcdev構(gòu)造指針從一種inode中取得主設(shè)備號(hào)和次設(shè)備號(hào):unsignedintiminor(structinode*inode);unsignedintimajor(structinode*inode);第20頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造注冊(cè)設(shè)備
,在模塊或驅(qū)動(dòng)初始化時(shí)調(diào)用Linux-2.4及之前Linux-2.6intregister_chrdev(unsignedintmajor,constchar*name, structfile_operations*fops)如何操作字符設(shè)備接口voidcdev_init(structcdev*,structfile_operations*);intcdev_add(structcdev*,dev_t,unsigned);第21頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造注銷設(shè)備:在模塊卸載時(shí)調(diào)用Linux-2.4及之前Linux-2.6intunregister_chrdev(unsignedintmajor, constchar*name);voidcdev_del(structcdev*);第22頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造//設(shè)備驅(qū)動(dòng)模塊加載函數(shù)staticint__initxxx_init(void){ ... cdev_init(&xxx_dev.cdev,&xxx_fops);//初始化cdev xxx_dev.cdev.owner=THIS_MODULE; //獲取字符設(shè)備號(hào) if(xxx_major) { register_chrdev_region(xxx_dev_no,1,DEV_NAME); } else { alloc_chrdev_region(&xxx_dev_no,0,1,DEV_NAME); } ret=cdev_add(&xxx_dev.cdev,xxx_dev_no,1);//注冊(cè)設(shè)備 ...}第23頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造/*設(shè)備驅(qū)動(dòng)模塊卸載函數(shù)*/staticvoid__exitxxx_exit(void){ unregister_chrdev_region(xxx_dev_no,1);//釋放占用設(shè)備號(hào)
cdev_del(&xxx_dev.cdev);//注銷設(shè)備 ...}第24頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造打開(kāi)模塊使用計(jì)數(shù)加1識(shí)別次設(shè)備號(hào)硬件操作:檢查設(shè)備有關(guān)錯(cuò)誤(諸如設(shè)備未就緒或類似硬件問(wèn)題);假如設(shè)備是初次打開(kāi),則對(duì)其初始化;假如有中斷操作,申請(qǐng)中斷處理程序;intopen(structinode*inode,structfile*filp);第25頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造關(guān)閉模塊使用計(jì)數(shù)減1釋放由open分派,保存在filp>private_data里所有內(nèi)容。硬件操作:假如申請(qǐng)了中斷,則釋放中斷處理程序。在最后一次關(guān)閉操作時(shí)關(guān)閉設(shè)備。intrelease(structinode*inode,structfile*filp);第26頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造
read/writessize_tread(structfile*filp,char__user*buff,size_tcount,loff_t*offp);ssize_twrite(structfile*filp,constchar__user*buff,size_tcount,loff_t*offp);指向顧客空間緩沖區(qū),這個(gè)緩沖區(qū)或者保存將寫入數(shù)據(jù),或者是一種寄存新讀入數(shù)據(jù)空緩沖區(qū)。顧客在文獻(xiàn)中存取操作位置第27頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造
顧客空間和內(nèi)核空間之間數(shù)據(jù)拷貝過(guò)程,不能簡(jiǎn)單用指針操作或者memcpy來(lái)進(jìn)行數(shù)據(jù)拷貝顧客空間數(shù)據(jù)是能夠被換出,會(huì)產(chǎn)生一種頁(yè)面失效異常。顧客空間地址無(wú)法在內(nèi)核空間中使用。顧客空間和內(nèi)核空間之間進(jìn)行數(shù)據(jù)拷貝函數(shù):假如要復(fù)制內(nèi)存是簡(jiǎn)單類型,如char、int、long等,put_user()和get_user()unsignedlongcopy_from_user(void*to,constvoid__user*from,unsignedlongcount);unsignedlongcopy_to_user(void__user*to,constvoid*from,unsignedlongcount);第28頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造讀設(shè)備模板ssize_txxx_read(structfile*filp,char__user*buf, size_tcount,loff_t*f_pos){ ... copy_to_user(buf,...,...); ...}寫設(shè)備模板ssize_txxx_write(structfile*filp,constchar__user*buf, size_tcount,loff_t*f_pos){ ... copy_from_user(...,buf,...); ...}第29頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造
ioctl函數(shù)為設(shè)備驅(qū)動(dòng)程序執(zhí)行“命令”提供了一種特有入口點(diǎn)用來(lái)設(shè)置或者讀取設(shè)備屬性信息。intioctl(structinode*inode,structfile*filp, unsignedintcmd,unsignedlongarg);事先定義IO控制命令代碼arg為對(duì)應(yīng)于cmd命令參數(shù)第30頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造cmd參數(shù)定義不推薦用0x1,0x2,0x3之類值Linux對(duì)ioctl()cmd參數(shù)有特殊定義構(gòu)造命令編號(hào)宏:_IO(type,nr)用于構(gòu)造無(wú)參數(shù)命令編號(hào);_IOR(type,nr,datatype)用于構(gòu)造從驅(qū)動(dòng)程序中讀取數(shù)據(jù)命令編號(hào);_IOW(type,nr,datatype)用于寫入數(shù)據(jù)命令;_IOWR(type,nr,datatype)用于雙向傳輸。type和number位字段通過(guò)參數(shù)傳入,而size位字段通過(guò)對(duì)datatype參數(shù)取sizeof取得。
設(shè)備類型(type)
序列號(hào)(number)方向(direction)
數(shù)據(jù)尺寸(size)
8bit
8bit
2bit13/14bit第31頁(yè)字符設(shè)備驅(qū)動(dòng)程序基本構(gòu)造Ioctl函數(shù)模板intxxx_ioctl(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg){ ... switch(cmd) { caseXXX_CMD1: ... break; caseXXX_CMD2: ... break; default:///*不能支持命令*/ return-ENOTTY; } return0;}第32頁(yè)階段總結(jié)第33頁(yè)階段總結(jié)第34頁(yè)添加驅(qū)動(dòng)程序到內(nèi)核配備內(nèi)核編譯內(nèi)核添加驅(qū)動(dòng)程序到內(nèi)核中第35頁(yè)添加驅(qū)動(dòng)程序到內(nèi)核配備內(nèi)核配備命令包括: makeconfig makemenuconfig makexconfig makegconfig
可通過(guò)“上”、“下”、“左”、“右”鍵移動(dòng)菜單,選擇某項(xiàng)按“Y”,取消選擇按“N”,假如選擇某項(xiàng)編譯為模塊按“M”,進(jìn)入子菜單按“Enter”,返回上一級(jí)菜單按“Esc”使用makeconfig、makemenuconfig等命令后,會(huì)生成一種.config配備文獻(xiàn)(是隱身文獻(xiàn),通過(guò)ls–a才能看到)
第36頁(yè)添加驅(qū)動(dòng)程序到內(nèi)核編譯內(nèi)核可用如下命令編譯內(nèi)核:makeARC=armCROSS_COMPILE=arm-linux-zImage源代碼根目錄Makefile中將ARCH和CROSS_COMPILE直接指定為arm和arm-linux-,如:
這樣就沒(méi)有必要每次編譯時(shí)候都指定體系構(gòu)造和交叉編譯器了,只須使用下面命令就能夠了:
makezImageARCH ?=armCROSS_COMPILE ?=arm-linux-第37頁(yè)添加驅(qū)動(dòng)程序到內(nèi)核添加驅(qū)動(dòng)程序到內(nèi)核Linux2.6內(nèi)核配備系統(tǒng)由下列3個(gè)部分組成。Makefile:分布在Linux內(nèi)核源代碼中Makefite定義Linux內(nèi)核編譯規(guī)則配備文獻(xiàn)(Kconfig):給顧客提供配備選擇功能。配備工具:包括配備命令解釋器(對(duì)配備腳本中使用配備命令進(jìn)行解釋)配備顧客界面(提供字符界面和圖形界面)。這些配備工具都是使用腳本語(yǔ)言編寫,如Tcl/TK、Perl等。在Linux內(nèi)核中增加程序需要完成下列3項(xiàng)工作。將編寫源代碼復(fù)制到Linux內(nèi)核源代碼對(duì)應(yīng)目錄。在目錄Kconfig文獻(xiàn)中增加新源代碼對(duì)應(yīng)項(xiàng)目標(biāo)編譯配備選項(xiàng)。在目錄Makefile文獻(xiàn)中增加對(duì)新源代碼編譯條目。第38頁(yè)添加驅(qū)動(dòng)程序到內(nèi)核實(shí)例:在內(nèi)核源代碼drivers目錄下為ARM體系構(gòu)造新增testdrivertestdriver樹(shù)形目錄:
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 快遞員工培訓(xùn)課件
- 寵物養(yǎng)殖租賃合同范本
- 金屬橋架合同范本
- 小學(xué)生食品安全課件
- 高低壓配電工程施工承包合同
- 檢驗(yàn)滅火器合同書
- 關(guān)于采購(gòu)辦公用品的申請(qǐng)報(bào)告與審批流程說(shuō)明
- 民族局離婚協(xié)議書
- 中學(xué)生課外閱讀指南觀后感
- 法律咨詢行業(yè)法律建議免責(zé)
- 新能源汽車驅(qū)動(dòng)電機(jī)及控制系統(tǒng)檢修課件 學(xué)習(xí)情境3:驅(qū)動(dòng)電機(jī)的檢修
- DB43T 744-2012 錳水質(zhì)在線自動(dòng)分析儀
- QC課題提高金剛砂地面施工一次合格率
- 北京中考語(yǔ)文2024年真題考點(diǎn)全面解讀
- 解讀2024年《學(xué)紀(jì)、知紀(jì)、明紀(jì)、守紀(jì)》全文課件
- 武漢版生命安全教育一年級(jí)-第19課《做好“四勤”防疾病》課件
- T-JMTX 022-2024 叉車安全使用與管理要求
- 2024-2030年中國(guó)染料敏化太陽(yáng)能電池(DSSC)行業(yè)市場(chǎng)發(fā)展趨勢(shì)與前景展望戰(zhàn)略研究報(bào)告
- 安徽省合肥市2024年小升初英語(yǔ)試卷(含答案)
- 研學(xué)旅行基地評(píng)估認(rèn)定評(píng)分表
- 第5課 用發(fā)展的觀點(diǎn)看問(wèn)題-【中職專用】2024年中職思想政治《哲學(xué)與人生》金牌課件(高教版2023·基礎(chǔ)模塊)
評(píng)論
0/150
提交評(píng)論