版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
字符設(shè)備驅(qū)動(dòng)第5章字符設(shè)備驅(qū)動(dòng)計(jì)算機(jī)科學(xué)技術(shù)系李偉民2012年8月字符設(shè)備驅(qū)動(dòng)提綱Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)
-Linux設(shè)備號(hào)管理
-一些重要的數(shù)據(jù)結(jié)構(gòu)globalmem設(shè)備驅(qū)動(dòng)
-globalmem驅(qū)動(dòng)編寫(xiě)方法和分析-globalmem設(shè)備驅(qū)動(dòng)在用戶空間的驗(yàn)證
字符設(shè)備驅(qū)動(dòng)引言Linux提供3種基本的設(shè)備驅(qū)動(dòng)接口,包括字符,塊設(shè)備和網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng),其中字符設(shè)備是應(yīng)用最廣,和用戶應(yīng)用程序聯(lián)系最直接的驅(qū)動(dòng)。比起塊設(shè)備或者網(wǎng)絡(luò)驅(qū)動(dòng)程序更加易于理解。字符設(shè)備驅(qū)動(dòng)字符設(shè)備開(kāi)發(fā)的基本步驟字符設(shè)備的特點(diǎn)像字節(jié)流一樣來(lái)存取的設(shè)備(如同文件)通過(guò)/dev下的文件系統(tǒng)結(jié)點(diǎn)來(lái)訪問(wèn)通常至少需要實(shí)現(xiàn)open,close,read,和write等系統(tǒng)調(diào)用只能順序訪問(wèn)的數(shù)據(jù)通道,不能前后移動(dòng)訪問(wèn)指針。特例:比如framebuffer設(shè)備就是這樣的設(shè)備,應(yīng)用程序可以使用mmap或lseek訪問(wèn)圖像的各個(gè)區(qū)域。字符設(shè)備驅(qū)動(dòng)字符設(shè)備開(kāi)發(fā)的基本步驟確定主設(shè)備號(hào)和次設(shè)備號(hào)實(shí)現(xiàn)字符驅(qū)動(dòng)程序?qū)崿F(xiàn)file_operations結(jié)構(gòu)體實(shí)現(xiàn)初始化函數(shù),注冊(cè)字符設(shè)備實(shí)現(xiàn)銷(xiāo)毀函數(shù),釋放字符設(shè)備創(chuàng)建設(shè)備文件節(jié)點(diǎn)字符設(shè)備驅(qū)動(dòng)主設(shè)備號(hào)與次設(shè)備號(hào)主設(shè)備號(hào)與次設(shè)備號(hào)主設(shè)備號(hào):主設(shè)備號(hào)是內(nèi)核識(shí)別一個(gè)設(shè)備的標(biāo)識(shí)。整數(shù)(占12bits),范圍從0到4095,通常使用1到255。可以通過(guò)/proc/devices文件來(lái)查看驅(qū)動(dòng)系統(tǒng)設(shè)備的主設(shè)備號(hào)。次設(shè)備號(hào):次設(shè)備號(hào)由內(nèi)核使用,用于正確確定設(shè)備文件所指的設(shè)備,驅(qū)動(dòng)程序遍歷設(shè)備時(shí),每發(fā)現(xiàn)一個(gè)它能驅(qū)動(dòng)的設(shè)備,就創(chuàng)建一個(gè)設(shè)備對(duì)象,并為其分配一個(gè)次設(shè)備號(hào)以區(qū)分不同的設(shè)備。這樣當(dāng)應(yīng)用程序訪問(wèn)設(shè)備節(jié)點(diǎn)時(shí)驅(qū)動(dòng)程序就可以根據(jù)次設(shè)備號(hào)知道它所訪問(wèn)的設(shè)備了。整數(shù)(占20bits),范圍從0到1048575,一般使用0到255。字符設(shè)備驅(qū)動(dòng)主設(shè)備號(hào)與次設(shè)備號(hào)ls-l/devcrw-r1rootroot1,1Jan100:00memcrw-r1rootroot1,2Jan100:00kmemcrw-rw-rw-1rootroot1,3Jan100:00nullcrw-r1rootroot1,4Jan100:00portcrw-rw-rw-1rootroot1,5Jan100:00zerocrw-rw-rw-1rootroot1,7Jan100:00fullcrw-r--r--1rootroot1,8Jan100:00randomcrw-r--r--1rootroot1,9Jan100:00urandomcrw-rw-rw-1rootroot5,0Jan100:00ttycrw1rootroot5,1Jan100:00consolecrw-rw-rw-1rootroot5,2Jan100:00ptmxdrwxr-xr-x1rootroot0Jan100:00ptydrwxr-xr-x2rootroot0Jan100:00ptsdrwxr-xr-x1rootroot0Jan100:00rddrwxr-xr-x1rootroot0Jan100:00mtddrwxr-xr-x1rootroot0Jan100:00mtdblockcrw1rootroot4,64Jan100:15ttyS0crw1rootroot4,65Jan100:00ttyS1crw1rootroot4,66Jan100:00ttyS2crw1rootroot4,67Jan100:00ttyS3crw1rootroot4,68Jan100:00ttyS4drwxr-xr-x1rootroot0Jan100:00miscc:字符設(shè)備b:塊設(shè)備主設(shè)備號(hào)次設(shè)備號(hào)字符設(shè)備驅(qū)動(dòng)設(shè)備編號(hào)的內(nèi)部表達(dá)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)字符設(shè)備驅(qū)動(dòng)主設(shè)備號(hào)與次設(shè)備號(hào)分配主設(shè)備號(hào)手工分配:找一個(gè)內(nèi)核沒(méi)有使用過(guò)的主設(shè)備號(hào)來(lái)使用動(dòng)態(tài)分配:我們通常不知道設(shè)備將要使用哪些主設(shè)備號(hào)#include<linux/fs.h>intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name);要分配的設(shè)備編號(hào)范圍的起始值,次設(shè)備號(hào)經(jīng)常為0所請(qǐng)求的連續(xù)設(shè)備編號(hào)的個(gè)數(shù)和該編號(hào)范圍關(guān)聯(lián)的設(shè)備名稱,它將出現(xiàn)在/proc/devices和sysfs中#include<linux/fs.h>intalloc_chrdev_resion(dev_t*dev,unsignedintfirstminor,
unsignedintcount,char*name);輸出的設(shè)備號(hào)要使用的被請(qǐng)求的第一個(gè)次設(shè)備號(hào)字符設(shè)備驅(qū)動(dòng)主設(shè)備號(hào)與次設(shè)備號(hào)釋放設(shè)備號(hào)voidunregister_chrdev_region(dev_tfirst,unsignedintcount);通常在模塊的清除函數(shù)中調(diào)用。字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)cdev結(jié)構(gòu)體Linux2.6內(nèi)核中,使用cdev結(jié)構(gòu)體描述一個(gè)字符設(shè)備structcdev{ structkobjectkobj;/*內(nèi)嵌的kobject對(duì)象*/ structmodule*owner;/*所屬模塊*/ structfile_operations*ops;/*文件操作結(jié)構(gòu)體*/ structlist_headlist; dev_tdev;/*設(shè)備號(hào)*/ unsignedintcount;};字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(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之間的連接函數(shù)用于動(dòng)態(tài)申請(qǐng)一個(gè)cdev內(nèi)存分別向系統(tǒng)刪除一個(gè)cdev,完成字符設(shè)備的注銷(xiāo),通常在模塊的卸載函數(shù)中調(diào)用分別向系統(tǒng)添加一個(gè)cdev,完成字符設(shè)備的注冊(cè),通常在模塊加載函數(shù)中調(diào)用字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file_operations結(jié)構(gòu)體字符驅(qū)動(dòng)和內(nèi)核的接口,在include/linux/fs.h中定義,它定義了維系在設(shè)備驅(qū)動(dòng)上的操作函數(shù)。在進(jìn)程PCB中,每個(gè)打開(kāi)文件,包括設(shè)備文件(內(nèi)部用一個(gè)structfile結(jié)構(gòu)來(lái)代表,稍后我們會(huì)看到)與它自身的函數(shù)集合相關(guān)連,它通過(guò)包含一個(gè)稱為f_op的指向一個(gè)file_operations結(jié)構(gòu)成員指針建立關(guān)系字符驅(qū)動(dòng)只要實(shí)現(xiàn)一個(gè)file_operations結(jié)構(gòu)體,并注冊(cè)到內(nèi)核中,內(nèi)核就有了操作此設(shè)備的能力用戶通過(guò)系統(tǒng)調(diào)用open,read,write等在這個(gè)結(jié)構(gòu)中有相應(yīng)的方法對(duì)應(yīng)字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員structmodule*owner:它是一個(gè)指向擁有這個(gè)結(jié)構(gòu)的模塊的指針,它被簡(jiǎn)單初始化為T(mén)HIS_MODULE,一個(gè)在<linux/module.h>中定義的宏。loff_t(*llseek)(structfile*,loff_t,int):
llseek方法用作改變文件中的當(dāng)前讀/寫(xiě)位置,并且新位置作為(正的)返回值。ssize_t(*read)(structfile*,char__user*,size_t,loff_t*):用來(lái)從設(shè)備中獲取數(shù)據(jù)。ssize_t(*aio_read)(structkiocb*,char__user*,size_t,loff_t):初始化一個(gè)異步讀--可能在函數(shù)返回前不結(jié)束的讀操作.字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*):發(fā)送數(shù)據(jù)給設(shè)備.如果NULL,-EINVAL,如果非負(fù),返回值代表成功寫(xiě)的字節(jié)數(shù)。ssize_t(*aio_write)(structkiocb*,constchar__user*,size_t,loff_t*):初始化設(shè)備上的一個(gè)異步寫(xiě)。
int(*readdir)(structfile*,void*,filldir_t):對(duì)于設(shè)備文件這個(gè)成員應(yīng)當(dāng)為NULL;它用來(lái)讀取目錄,并且僅對(duì)文件系統(tǒng)有用unsignedint(*poll)(structfile*,structpoll_table_struct*):poll方法是3個(gè)系統(tǒng)調(diào)用的后端:poll,epoll,和select,都用作查詢對(duì)一個(gè)或多個(gè)文件描述符的讀或?qū)懯欠駮?huì)阻塞字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員
int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong):ioctl系統(tǒng)調(diào)用提供了發(fā)出設(shè)備特定命令的方法(例如格式化軟盤(pán)的一個(gè)磁道,這不是讀也不是寫(xiě))。int(*mmap)(structfile*,structvm_area_struct*):mmap用來(lái)請(qǐng)求將設(shè)備內(nèi)存映射到進(jìn)程的地址空間.如果這個(gè)方法是NULL,mmap系統(tǒng)調(diào)用返回–ENODEV。int(*open)(structinode*,structfile*):盡管這常常是對(duì)設(shè)備文件進(jìn)行的第一個(gè)操作,不要求驅(qū)動(dòng)聲明一個(gè)對(duì)應(yīng)的方法.如果這個(gè)項(xiàng)是NULL,設(shè)備打開(kāi)一直成功,但是你的驅(qū)動(dòng)不會(huì)得到通知.int(*flush)(structfile*):flush操作在進(jìn)程關(guān)閉它的設(shè)備文件描述符的拷貝時(shí)調(diào)用,它應(yīng)當(dāng)執(zhí)行(并且等待)設(shè)備的任何未完成的操作.如果flush為NULL,內(nèi)核簡(jiǎn)單地忽略用戶應(yīng)用程序的請(qǐng)求.字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員int(*release)(structinode*,structfile*):在文件結(jié)構(gòu)被釋放時(shí)用該操作。int(*fsync)(structfile*,structdentry*,int):這個(gè)方法是fsync系統(tǒng)調(diào)用的后端,用戶調(diào)用來(lái)刷新任何掛著的數(shù)據(jù)。int(*fasync)(int,structfile*,int):這個(gè)操作用來(lái)通知設(shè)備它的FASYNC標(biāo)志的改變int(*lock)(structfile*,int,structfile_lock*):lock方法用來(lái)實(shí)現(xiàn)文件加鎖ssize_t(*sendfile)(structfile*,loff_t*,size_tread_actor_t,void*):sendpage是sendfile的另一半;它由內(nèi)核調(diào)用來(lái)發(fā)送數(shù)據(jù),一次一頁(yè),到對(duì)應(yīng)的文件.設(shè)備驅(qū)動(dòng)上不實(shí)現(xiàn)sendpage字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員int(*release)(structinode*,structfile*):在文件結(jié)構(gòu)被釋放時(shí)用該操作。int(*fsync)(structfile*,structdentry*,int):這個(gè)方法是fsync系統(tǒng)調(diào)用的后端,用戶調(diào)用來(lái)刷新任何掛著的數(shù)據(jù)。int(*fasync)(int,structfile*,int):這個(gè)操作用來(lái)通知設(shè)備它的FASYNC標(biāo)志的改變int(*lock)(structfile*,int,structfile_lock*):lock方法用來(lái)實(shí)現(xiàn)文件加鎖ssize_t(*sendfile)(structfile*,loff_t*,size_tread_actor_t,void*):sendpage是sendfile的另一半;它由內(nèi)核調(diào)用來(lái)發(fā)送數(shù)據(jù),一次一頁(yè),到對(duì)應(yīng)的文件.設(shè)備驅(qū)動(dòng)上不實(shí)現(xiàn)sendpage字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file結(jié)構(gòu)體file結(jié)構(gòu)與用戶空間程序中的FILE沒(méi)有任何關(guān)聯(lián),F(xiàn)ILE在C庫(kù)中定義且不會(huì)出現(xiàn)在內(nèi)核代碼中,structfile是一個(gè)內(nèi)核結(jié)構(gòu),不會(huì)出現(xiàn)在用戶程序。file結(jié)構(gòu)代表一個(gè)打開(kāi)的文件(不限定于設(shè)備驅(qū)動(dòng)程序)。它由內(nèi)核在open時(shí)創(chuàng)建,并傳遞給在該文件上進(jìn)行操作的所有函數(shù),直到close函數(shù)。在文件的所有實(shí)例都被關(guān)閉之后,內(nèi)核會(huì)釋放。指向structfile的指針通常被稱為filp。字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file結(jié)構(gòu)體的主要成員mode_tf_mode:文件模式,它通過(guò)FMODE_READ和FMODE_WRITE來(lái)標(biāo)識(shí)文件是否可讀或可寫(xiě)(或可讀寫(xiě))。loff_tf_pos:初始化當(dāng)前讀寫(xiě)位置。驅(qū)動(dòng)可以讀這個(gè)值,如果它需要知道文件中的當(dāng)前位置,但是正常地不應(yīng)該改變它;讀和寫(xiě)會(huì)使用它們接收到的最后那個(gè)指針參數(shù)來(lái)更新一個(gè)位置,代替直接作用于filp->f_pos。
unsignedintf_flags:這些是文件標(biāo)志,例如O_RDONLY,O_NONBLOCK,和O_SYNC。驅(qū)動(dòng)應(yīng)當(dāng)檢查O_NONBLOCK標(biāo)志來(lái)看是否是請(qǐng)求非阻塞操作;其他標(biāo)志很少使用。字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)file結(jié)構(gòu)體的主要成員structfile_operations*f_op:和文件關(guān)聯(lián)的操作.內(nèi)核安排指針作為它的open實(shí)現(xiàn)的一部分,接著讀取它當(dāng)它需要分派任何的操作時(shí).filp->f_op中的值從不由內(nèi)核保存為后面的引用;這意味著你可改變你的文件關(guān)聯(lián)的文件操作,在你返回調(diào)用者之后新方法會(huì)起作用。void*private_data:open系統(tǒng)調(diào)用設(shè)置這個(gè)指針為NULL,在為驅(qū)動(dòng)調(diào)用open方法之前.你可自由使用這個(gè)成員或者忽略它;你可以使用這個(gè)成員來(lái)指向分配的數(shù)據(jù),但是接著你必須記住在內(nèi)核銷(xiāo)毀文件結(jié)構(gòu)之前,在release方法中釋放那個(gè)內(nèi)存。
structdentry*f_dentry:關(guān)聯(lián)到文件的目錄入口(dentry)結(jié)構(gòu)。
字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)inode結(jié)構(gòu)體inode結(jié)構(gòu)由內(nèi)核在內(nèi)部用來(lái)表示文件.因此,它和代表打開(kāi)文件描述符的文件結(jié)構(gòu)是不同的.可能有代表單個(gè)文件的多個(gè)打開(kāi)描述符的許多文件結(jié)構(gòu),但是它們都指向一個(gè)單個(gè)inode結(jié)構(gòu).inode結(jié)構(gòu)包含大量關(guān)于文件的信息.作為一個(gè)通用的規(guī)則,這個(gè)結(jié)構(gòu)只有2個(gè)成員對(duì)于編寫(xiě)驅(qū)動(dòng)代碼有用:dev_ti_rdev:對(duì)表示設(shè)備文件的inode結(jié)構(gòu),這個(gè)成員包含實(shí)際的設(shè)備編號(hào)structcdev*i_cdev:代表字符設(shè)備;當(dāng)節(jié)點(diǎn)指的是一個(gè)字符設(shè)備文件時(shí),這個(gè)成員包含一個(gè)指針,指向這個(gè)結(jié)構(gòu)。從一個(gè)inode中獲取主次編號(hào):unsignedintiminor(structinode*inode);unsignedintimajor(structinode*inode);字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)注冊(cè)設(shè)備,在模塊或驅(qū)動(dòng)初始化時(shí)調(diào)用Linux2.4及之前:Linux2.6:intregister_chrdev(unsignedintmajor,constchar*name, structfile_operations*fops)voidcdev_init(structcdev*,structfile_operations*);intcdev_add(structcdev*,dev_t,unsigned);在運(yùn)行時(shí)獲取一個(gè)獨(dú)立的cdev結(jié)構(gòu)該設(shè)備關(guān)聯(lián)的設(shè)備編號(hào)的數(shù)量驅(qū)動(dòng)程序沒(méi)有完全準(zhǔn)備好處理設(shè)備上的操作,不能調(diào)用cdev_add字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)注銷(xiāo)設(shè)備,在模塊或驅(qū)動(dòng)卸載時(shí)調(diào)用Linux2.4及之前:Linux2.6:intunregister_chrdev(unsignedintmajor, constchar*name);voidcdev_del(structcdev*);字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(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è)備 ...}字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(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);//注銷(xiāo)設(shè)備 ...}字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)設(shè)備的打開(kāi)open應(yīng)當(dāng)進(jìn)行下面的工作:1)檢查設(shè)備特定的錯(cuò)誤(例如設(shè)備沒(méi)準(zhǔn)備好,或者類似的硬件錯(cuò)誤
2)如果它第一次打開(kāi),初始化設(shè)備
3)如果需要,更新f_op指針,模塊計(jì)數(shù)加1 4)分配并填充要放進(jìn)filp->private_data的任何數(shù)據(jù)結(jié)構(gòu)。
5)識(shí)別次設(shè)備號(hào)
6)如果有中斷操作,申請(qǐng)中斷處理程序。intopen(structinode*inode,structfile*filp);字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)設(shè)備的關(guān)閉release方法在應(yīng)用程序調(diào)用close()系統(tǒng)調(diào)用時(shí)被調(diào)用,它的角色是open的反面. 1)釋放open分配在filp->private_data中的任何東西
2)在最后的close關(guān)閉設(shè)備,模塊計(jì)數(shù)減1
3)如果申請(qǐng)了中斷,則釋放中斷處理程序.intrelease(structinode*inode,structfile*filp);字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(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ū)或者保存將寫(xiě)入的數(shù)據(jù),或者是一個(gè)存放新讀入數(shù)據(jù)的空緩沖區(qū)。用戶在文件中存取操作的位置buff參數(shù)是用戶空間指針,內(nèi)核代碼不能直接引用其中的內(nèi)容。字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)用戶空間與內(nèi)核空間的數(shù)據(jù)拷貝不能簡(jiǎn)單的用指針操作或者memcpy來(lái)進(jìn)行數(shù)據(jù)拷貝,要用內(nèi)核函數(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);字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)讀設(shè)備模板ssize_t
xxx_read(structfile*filp,char__user*buf,
size_tcount,loff_t*f_pos){ ...
copy_to_user(buf,...,...); ...}寫(xiě)設(shè)備模板
ssize_t
xxx_write(structfile*filp,constchar__user*buf,
size_tcount,loff_t*f_pos){ ...
copy_from_user(...,buf,...); ...}字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)ioctl函數(shù)ioctl函數(shù)主要完成以下兩個(gè)功能:
1)為設(shè)備驅(qū)動(dòng)程序執(zhí)行“命令”提供了一個(gè)特有的入口點(diǎn)
2)用來(lái)設(shè)置或者讀取設(shè)備的屬性信息
intioctl(structinode*inode,structfile*filp, unsignedintcmd,unsignedlongarg);事先定義的IO控制命令代碼arg為對(duì)應(yīng)于cmd命令的參數(shù)字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)cmd參數(shù)的定義不推薦用0x1,0x2,0x3之類的值,會(huì)導(dǎo)致不同的設(shè)備驅(qū)動(dòng)擁有相同的命令號(hào)。Linux對(duì)ioctl()的cmd參數(shù)有特殊的定義
設(shè)備類型(type)
序列號(hào)(number)方向(direction)
數(shù)據(jù)尺寸(size)
8bit
8bit
2bit13/14bit字符設(shè)備驅(qū)動(dòng)Linux字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)cmd參數(shù)的定義內(nèi)核還定義了以下四個(gè)宏來(lái)輔助生成命令:IO(type,nr)用于構(gòu)造無(wú)參數(shù)的命令編號(hào);_IOR(type,nr,datatype)用于構(gòu)造從驅(qū)動(dòng)程序中讀取數(shù)據(jù)的命令編號(hào)
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度軟件測(cè)試工程師保密合同及質(zhì)量保證協(xié)議3篇
- 2025年度店鋪股份質(zhì)押與融資服務(wù)合同范本2篇
- 二零二五年度智慧城市基礎(chǔ)設(shè)施建設(shè)項(xiàng)目承包合同樣本3篇
- 科學(xué)思維在學(xué)科復(fù)習(xí)中的運(yùn)用
- 網(wǎng)絡(luò)安全教育在學(xué)校中的創(chuàng)新實(shí)踐與策略研究
- Unit 6【單元測(cè)試·基礎(chǔ)卷】-2023-2024學(xué)年九年級(jí)英語(yǔ)上冊(cè)(牛津上海版)(解析版)
- 二零二五年度車(chē)輛抵押借款合同爭(zhēng)議解決機(jī)制4篇
- 2025年度土地租賃合同參考范本3篇
- 2025年度個(gè)人水電安裝與維護(hù)承包服務(wù)合同4篇
- 2025版?zhèn)€人二手房交易合同附房屋維修責(zé)任說(shuō)明2篇
- 多子女贍養(yǎng)老人協(xié)議書(shū)范文
- 安踏運(yùn)動(dòng)品牌營(yíng)銷(xiāo)策略研究
- 彩票市場(chǎng)銷(xiāo)售計(jì)劃書(shū)
- 骨科抗菌藥物應(yīng)用分析報(bào)告
- 支付行業(yè)反洗錢(qián)與反恐怖融資
- 百詞斬托福詞匯excel版本
- 基礎(chǔ)設(shè)施綠色施工技術(shù)研究
- 寶鋼BQB 481-2023全工藝?yán)滠堉蓄l無(wú)取向電工鋼帶文件
- 車(chē)輛定損情況確認(rèn)書(shū)范本
- 高中英語(yǔ)新課標(biāo)詞匯表(附詞組)
- 2022年高考湖南卷生物試題(含答案解析)
評(píng)論
0/150
提交評(píng)論