linux內(nèi)核驅(qū)動(dòng)模塊編寫ioctl_第1頁(yè)
linux內(nèi)核驅(qū)動(dòng)模塊編寫ioctl_第2頁(yè)
linux內(nèi)核驅(qū)動(dòng)模塊編寫ioctl_第3頁(yè)
linux內(nèi)核驅(qū)動(dòng)模塊編寫ioctl_第4頁(yè)
linux內(nèi)核驅(qū)動(dòng)模塊編寫ioctl_第5頁(yè)
已閱讀5頁(yè),還剩14頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

如果你對(duì)內(nèi)核驅(qū)動(dòng)模塊一無(wú)所知,請(qǐng)先學(xué)習(xí)內(nèi)核驅(qū)動(dòng)模塊的基礎(chǔ)知識(shí)。如果你已經(jīng)入門了內(nèi)核驅(qū)動(dòng)模塊,但是仍感覺(jué)有些模糊,不能從整體來(lái)了解一個(gè)內(nèi)核驅(qū)動(dòng)模塊的結(jié)構(gòu),請(qǐng)賞讀一下這篇拙文。如果你已經(jīng)從事內(nèi)核模塊編程N(yùn)年,并且道行高深,也請(qǐng)不吝賜教一下文中的疏漏錯(cuò)誤。本文中我將實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Linux字符設(shè)備,旨在大致勾勒出linux內(nèi)核模塊的編寫方法的輪廓。其中重點(diǎn)介紹ioctl的用途。我把這個(gè)簡(jiǎn)單的Linux字符設(shè)備模塊命名為hello_mod.設(shè)備類型名為hello_class設(shè)備名為hello該設(shè)備是一個(gè)虛擬設(shè)備,模塊加載時(shí)會(huì)在/sys/class/中創(chuàng)建名為hello_class的邏輯設(shè)備,在/dev/中創(chuàng)建hello的物理設(shè)備文件。模塊名為hello_mod,可接受輸入字符串?dāng)?shù)據(jù)(長(zhǎng)度小于128),處理該輸入字符串之后可向外輸出字符串。并且可以接受ioctl()函數(shù)控制內(nèi)部處理字符串的方式。例如:通過(guò)write函數(shù)寫入"Tom",通過(guò)ioctl函數(shù)設(shè)置langtype=chinese,通過(guò)read函數(shù)讀出的數(shù)據(jù)將會(huì)是"你好!Tom/n"通過(guò)write函數(shù)寫入“Tom",通過(guò)ioctl函數(shù)設(shè)置langtype=english,通過(guò)read函數(shù)讀出的數(shù)據(jù)將會(huì)是"hello!Tom/n"通過(guò)write函數(shù)寫入“Tom",通過(guò)ioctl函數(shù)設(shè)置langtype=pinyin,通過(guò)read函數(shù)讀出的數(shù)據(jù)將會(huì)是"nihao!Tom/n"一般的內(nèi)核模塊中不會(huì)負(fù)責(zé)設(shè)備類別和節(jié)點(diǎn)的創(chuàng)建,我們?cè)诰幾g完之后會(huì)得到0或者.1<0文件,然后insmod之后需要mknod來(lái)創(chuàng)建相應(yīng)文件,這個(gè)簡(jiǎn)單的例子中我們讓驅(qū)動(dòng)模塊加載時(shí)負(fù)責(zé)自動(dòng)創(chuàng)建設(shè)備類別和設(shè)備文件。這個(gè)功能有兩個(gè)步驟,創(chuàng)建設(shè)備類別文件class_create();創(chuàng)建設(shè)備文件device_create();關(guān)于這兩個(gè)函數(shù)的使用方法請(qǐng)參閱其他資料。linux設(shè)備驅(qū)動(dòng)的編寫相對(duì)windows編程來(lái)說(shuō)更容易理解一點(diǎn)因?yàn)椴恍枰幚鞩RP,應(yīng)用層函數(shù)和內(nèi)核函數(shù)的關(guān)聯(lián)方式淺顯易懂。比如當(dāng)應(yīng)曾函數(shù)對(duì)我的設(shè)備調(diào)用了open()函數(shù),而最終這個(gè)應(yīng)用層函數(shù)會(huì)調(diào)用我的設(shè)備中的自定義open()函數(shù),這個(gè)函數(shù)要怎么寫呢,我在我的設(shè)備中定義的函數(shù)名是hello_mod_open,注意函數(shù)名是可以隨意定義,但是函數(shù)簽名是要符合內(nèi)核要求的,具體的定義是怎么樣請(qǐng)W<linux/fs.h>staticinthello_mod_open(structinode*,structfile*);這樣就定義了內(nèi)核中的open函數(shù),這只是定義還需要與我們自己的模塊關(guān)聯(lián)起來(lái),這就要用到一個(gè)結(jié)構(gòu)structfile_operations這個(gè)結(jié)構(gòu)里面的成員是對(duì)應(yīng)于設(shè)備操作的各種函數(shù)的指針。我在設(shè)備中用到了這些函數(shù)所以就如下定義,注意下面的寫法不是標(biāo)準(zhǔn)ANSIC的語(yǔ)法,而是GNU擴(kuò)展語(yǔ)法。structfile_operationshello_mod_fops={.owner=THIS_MODULE,.open=hello_mod_open,.read=hello_mod_read,.write=hello_mod_write,.ioctl=hello_mod_ioctl,.release=hello_mod_release,};這個(gè)結(jié)構(gòu)體變量定義好之后我們?cè)谀K初始化函數(shù)中就可以通過(guò)register_chrdev()或者填充cdev結(jié)構(gòu)來(lái)關(guān)聯(lián)所有的操作到我們的模塊函數(shù)了。和設(shè)備交互的數(shù)據(jù)我們總稱為"數(shù)據(jù)",但是大致可劃分為兩種"功能數(shù)據(jù)":我們要輸入設(shè)備處理的和設(shè)備處理完之后輸出的數(shù)據(jù)。"控制數(shù)據(jù)":我們用來(lái)控制設(shè)備特性功能的命令和參數(shù)。open,read,write,release等函數(shù)是對(duì)一^驅(qū)動(dòng)模塊的使用,就是我們對(duì)"設(shè)備的功能"的使用。但是一個(gè)設(shè)備有可能有很多功能,那么我們要怎么控制設(shè)備讓設(shè)備完成指定的功能呢?據(jù)個(gè)例子來(lái)說(shuō):假如我們有一個(gè)翻譯機(jī)(姑且說(shuō)機(jī)吧,也可能是器)實(shí)體設(shè)備,主要功能是輸入中文,然后可以輸出各種語(yǔ)言對(duì)應(yīng)的翻譯結(jié)果,那這個(gè)機(jī)的功能就是翻譯,我們真正用來(lái)處理的數(shù)據(jù)是我們輸入的中文,我們要得到的"設(shè)備功能”就是翻譯后的輸出內(nèi)容,而各種語(yǔ)言則是我們的選擇控制了,我們可設(shè)定這個(gè)設(shè)備翻譯成何種語(yǔ)言。這就要求我們要向設(shè)備發(fā)送命令,設(shè)定目標(biāo)語(yǔ)言。請(qǐng)注意我們要發(fā)送的是兩個(gè)"控制數(shù)據(jù)",命令和參數(shù)。命令:一個(gè)設(shè)備可能有很多種行為,我們的命令就是代表我們要讓設(shè)備執(zhí)行何種行為。"復(fù)位","設(shè)定目標(biāo)語(yǔ)言","獲得當(dāng)前目標(biāo)語(yǔ)言"等參數(shù):對(duì)于某一個(gè)命令,可能需要參數(shù)可能不需要參數(shù)。比如:"復(fù)位"命令就不需要參數(shù)。"設(shè)定目標(biāo)語(yǔ)言"則需要傳入目標(biāo)語(yǔ)言的類型。"獲取目標(biāo)語(yǔ)言"則需要傳入一個(gè)能夠接收目標(biāo)語(yǔ)言類型的參數(shù)。自己畫了一個(gè)設(shè)備"數(shù)據(jù)流"圖,希望能加深理解。設(shè)備數(shù)調(diào)流囹-tishiEi需要處理的數(shù)據(jù)write()readf}處理之后的數(shù)據(jù)對(duì)于我們自己的設(shè)備我們就要自己定義設(shè)備命令了,如果你要想搞清命令的格式,請(qǐng)參考其他資料關(guān)于ioctl的參數(shù)的介紹。這里不打算介紹這個(gè),只介紹ioctl實(shí)際功能。定義自己的IO控制命令需要用到宏。這里直接寫出我的定義而不是介紹宏的實(shí)現(xiàn)#defineHELLO_MAGIC12#defineHELLO_IOCTL_RESETLANG_IO(HELLO_MAGIC,0)〃設(shè)置復(fù)位,這個(gè)命令不帶參數(shù)#defineHELLO_IOCTL_GETLANG_IOR(HELLO_MAGIC,1,int)//獲取當(dāng)前設(shè)備的語(yǔ)言類型參數(shù),參數(shù)是int型#defineHELLO_IOCTL_SETLANG_IOW(HELLO_MAGIC,2,int)〃設(shè)置設(shè)備的語(yǔ)言類型,參數(shù)是int多的不說(shuō)了,下面貼上完整代碼,懶人沒(méi)寫注釋。。不好意思。hellomod.c[cpp]viewplaincopyprint?/*Filename:hello.cDescription:hellomod*Version:1.0*Created:01/28/201105:07:55PM*Revision:none*Compiler:gcc**Author:Tishion(shion),****************Company:LIM*/#include<linux/module.h>#include<linux/init.h>#include<linux/kernel.h>#include<linux/fs.h>#include<linux/uaccess.h>#include<linux/semaphore.h>#include<linux/cdev.h>#include<linux/device.h>#include<linux/ioctl.h>#include<linux/slab.h>#include<linux/errno.h>#include<linux/string.h>#include"hello_mod_ioctl.h"#defineMAJOR_NUM250#defineMINOR_NUM0#defineIN_BUF_LEN256#defineOUT_BUF_LEN512MODULE_AUTHOR("Tishion");MODULE_DESCRIPTION("Hello_moddriverbytishion");staticstructclass*hello_class;staticstructcdevhello_cdev;staticdev_tdevnum=0;staticchar*modname="hello_mod";staticchar*devicename="hello";staticchar*classname="hello_class";staticintopen_count=0;staticstructsemaphoresem;staticspinlock_tspin=SPIN_LOCK_UNLOCKED;staticchar*inbuffer=NULL;staticchar*outbuffer=NULL;staticlang_tlangtype;staticinthello_mod_open(structinode*,structfile*);staticinthello_mod_release(structinode*,structfile*);staticssize_thello_mod_read(structfile*,char*,size_t,loff_t*);staticssize_thello_mod_write(structfile*,constchar*,size_t,loff_t*);staticinthello_mod_ioctl(structinode*,structfile*,unsignedint,unsignedlong);structfile_operationshello_mod_fops={.owner=THIS_MODULE,.open=hello_mod_open,.read=hello_mod_read,.write=hello_mod_write,.ioctl=hello_mod_ioctl,.release=hello_mod_release,};staticinthello_mod_open(structinode*inode,structfile*pfile){printk("+hello_mod_open()!/n");spin_lock(&spin);if(open_count){spin_unlock(&spin);returnEBUSY;}open_count++;spin_unlock(&spin);printk("hello_mod_open()!/n");return0;}staticinthello_mod_release(structinode*inode,structfile*pfile){printk("+hello_mod_release()!/n");open_count;printk("hello_mod_release()!/n");return0;}staticssize_thello_mod_read(structfile*pfile,char*user_buf,size_tlen,loff_t*off){printk("+hello_mod_read()!/n");if(down_interruptible(&sem)){returnERESTARTSYS;}memset(outbuffer,0,OUT_BUF_LEN);printk("+switch()/n");switch(langtype)caseenglish:printk(">incase:english/n");sprintf(outbuffer,"Hello!%s.",inbuffer);break;casechinese:printk(">incase:chinese/n");sprintf(outbuffer,"你好?。.",inbuffer);break;casepinyin:printk(">incase:pinyin/n");sprintf(outbuffer,"nihao!%s.",inbuffer);break;default:printk(">incase:default/n");break;}printk("switch()/n");if(copy_to_user(user_buf,outbuffer,len)){up(&sem);returnEFAULT;up(&sem);printk("hello_mod_read()!/n");return0;}staticssize_thello_mod_write(structfile*pfile,constchar*user_buf,size_tlen,loff_t*off){printk("+hello_mod_write()!/n");if(down_interruptible(&sem)){returnERESTARTSYS;}if(len>IN_BUF_LEN){printk("Outofinputbuffer/n");returnERESTARTSYS;}if(copy_from_user(inbuffer,user_buf,len)){up(&sem);returnEFAULT;up(&sem);printk("hello_mod_write()!/n");return0;}staticinthello_mod_ioctl(structinode*inode,structfile*pfile,unsignedintcmd,unsignedlongarg){interr=0;printk("+hello_mod_ioctl()!/n");printk("+switch()/n");switch(cmd){caseHELLO_IOCTL_RESETLANG:printk(">incase:HELLO_IOCTL_RESETLANG/n");langtype=english;break;caseHELLO_IOCTL_GETLANG:printk(">incase:HELLO_IOCTL_GETLANG/n");err=copy_to_user((int*)arg,&langtype,sizeof(int));break;caseHELLO_IOCTL_SETLANG:printk(">incase:HELLO_IOCTL_SETLANG/n");err=copy_from_user(&langtype,(int*)arg,sizeof(int));break;default:printk(">incase:default/n");err=ENOTSUPP;break;}printk("switch()/n");printk("hello_mod_ioctl()!/n");returnerr;}staticint__inithello_mod_init(void){intresult;printk("+hello_mod_init()!/n");devnum=MKDEV(MAJOR_NUM,MINOR_NUM);result=register_chrdev_region(devnum,1,modname);if(result<0){printk("hello_mod:can'tgetmajornumber!/n");returnresult;cdev_init(&hello_cdev,&hello_mod_fops);hello_cdev.owner=THIS_MODULE;hello_cdev.ops=&hello_mod_fops;result=cdev_add(&hello_cdev,devnum,1);if(result)printk("Failedatcdev_add()");hello_class=class_create(THIS_MODULE,classname);if(IS_ERR(hello_class)){printk("Failedatclass_create().Pleaseexec[mknod]beforeoperatethedevice/n");}else{device_create(hello_class,NULL,devnum,NULL,devicename);}open_count=0;langtype=english;inbuffer=(char*)kmalloc(IN_BUF_LEN,GFP_KERNEL);outbuffer=(char*)kmalloc(OUT_BUF_LEN,GFP_KERNEL);init_MUTEX(&sem);printk("hello_mod_init()!/n");return0;}staticvoid__exithello_mod_exit(void){printk("+hello_mod_exit!/n");kfree(inbuffer);kfree(outbuffer);cdev_del(&hello_cdev);device_destroy(hello_class,devnum);class_destroy(hello_class);unregister_chrdev_region(devnum,1);printk("hello_mod_exit!/n");return;}module_init(hello_mod_init);module_exit(hello_mod_exit);MODULE_LICENSE("GPL");

hello_mod_iotcl.h[cpp]viewplaincopyprint?/**==================================================================Filename:hellomodioctl.hDescription:Version:1.0Created:06/19/201110:24:20PMRevision:noneDescription:Version:1.0Created:06/19/201110:24:20PMRevision:noneCompiler:gccdefinethecmdsupportedbyhello_modAuthor:Tishion(shion),***************Company:LIM*/Author:Makefile#defineHELLOIOCTLRESETLANG_IO(HELLO_MAGIC,0)//setlangtype=english#defineHELLOIOCTLGETLANG_IOR(HELLO_MAGIC,1,int)Makefile#defineHELLOIOCTLRESETLANG_IO(HELLO_MAGIC,0)//setlangtype=english#defineHELLOIOCTLGETLANG_IOR(HELLO_MAGIC,1,int)//getlangtype#defineHELLOIOCTLSETLANG_IOW(HELLO_MAGIC,2,int)//setlangtypetypedefenum_lang_tenglish,Chinese,pinyin}lang_t;#endif#ifndef__HELLO_MOD_IOCTL_H#define__HELLO_MOD_IOCTL_H__#defineHELLOMAGIC12***********************************************#Makefilelinux2.6Module#ThismakefileiswrittenforUbuntu10.10#Itmaynotperfomancewithouterrosonthe#otherversionordistributions.護(hù)*********************************************#BY:tishion#Mail:***************#2011/06/19#**********************************************obj-m+=hello_mod.oCURRENT_PATH:=$(shellpwd)LINUX_KERNEL:=$(shelluname-r)LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)all:make-C$(LINUX_KERNEL_PATH)M=$(CURRENT_PATH)modulesclean:make-C$(LINUX_KERNEL_PATH)M=$(CURRENT_PATH)cleaninstall:insmodhello_mod.kounistall:rmmodhello_mod附上一用戶層測(cè)試文件,編譯后需要root身份執(zhí)行。/*Filename:hell_mod_test.c*Description:hell_modtestapp*Version:1.0Created:06/20/201101:44:11AMRevision:noneCompiler:gccAuthor:Tishion(shion),***************Author:Company:LIM*/#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<linux/ioctl.h>#include<string.h>#include<errno.h>#include"../hello_mod_ioctl.h"intmain(){charoutbuf[512];char*myname="tishion";lang_tlangtype=english;intfd=open("/dev/hello",O_RDWR,S_IRUSR|S_IWUSR);if(fd!=-1){write(fd,myname,strlen(myname)+1);langtype=chinese;ioctl(fd,HELLO_IOCTL_SETLANG,&langtype);read(fd,outbuf,512);printf("langtype=chinese:%s/n",outbuf);memset(outbuf,0,512);langtype=pinyin;ioctl(fd,HELLO_IOCTL_SETLANG,&langtype);read(fd,outbuf,512);printf("langtype=pinyin:%s/n",outbuf);memset(outbuf,0,512);ioctl(fd,HELLO_IOCTL_RESETLANG,&langtype);read(fd,outbuf,512);printf("langtype=english:%s/n",outbuf);}else{perror("Failedatopen():");}return0;}編譯和運(yùn)行過(guò)程圖[stilanftstlEMi-IWjufttu:ectt/tpro/kn'nfrljmoyhielLD-indJf14h^llicctl.h^kefllercM?Et相[.ihlDirtPsfiLM-IJbuntu:WpraJ1ttrZkarntlp^a/hffJ]iwlti■aice-C/utr<£rc/1invx碩我derfT,6?羽-15-genericH*/ho?MhIsn/srnjetf5/£pr?/kern^I^r^/h?lldi_ndBodulEi■ake[]];Lntaringdlrectary-rusr,"D1111心5“如|"£】,土找-小-砂口打北1(€(M]/i>Ope^shlo?^t>rOjKttft口ejkle電lD^D/h?llo_4Gd/h?l.cBuilding■ctfvltcp1.FWPlKt1>odui?CC/hew/s^iooi/^nojyfr/cprn-/ket*plpro/hell0_wHJ/h41l*_>c土nod..6LP[劉lQ<ifBrnj?Eit/cpr?■/kie電Ll,g■ak也[J];Ltawl^g一Ju"如lnu*-h*ddMA3-6.35-HEIE*[-網(wǎng)53L,g]4CttZCprfr/kt^nrltf^9/hv314_a4d}|>wdQIn*afidhrl.如PdtihXJrd'Shlfin;[5fti.?#sftlOfl-lRiur>cu;-*Apnoj*ctJ/cprO|/MtrfiFlpi*o/ri?Uo_*fti]lcdteit/[IRjufttu:4Ctt/ftpFk?m*?]41ftMis虬5t上[IrtSIw;JH<ikWFs.[,庠tH"10-.-frfl_tA-/MlN_*CLm$t.。[-IMuftiu:wroj?ett/cg?kt^nn1p^a/h^]/t#ctjls如,/hs-i一七h(yuǎn)l。Lin^ypp-c-Mnriv;咨好:Uil-ilon,>■那攔h.*4!CliMin.L>nBtypt"cnflIirtzMlloltlUnion.[-Ifeufttu:-Fp^oJ*cti/cproyWm*IprW踞1lo_*od^^-<tt】$如tfo『Ml1o_—m!j伸1_W^iMMUlRJuHu:T,(>nol虬t皿叩MHm?Ipro/MIliLfMutj,

[[shion^shlan-Ubunrui-jSt^il-43/HmrVMg/gq—Jun2112::32;J0^hian-Ubjnluke-rnel:[9779.141282]|triell^inod^initt)!)un2112::3Z:3。^hLofl'Ubuntukernel::9779.1416601|-tiallojnod_init(j!)un2112;ihlofl-Ubuntukern或;:9310.4629&6]jthellc_iMHi_npEri()!加2112l:33l11shion-Ubuntukernel:|9810.465136:-he1lc_tt?d_open()!Jun2112;閂3;11shlQ-fi-Ubuntv9旺■做*做:+heUc_fli>d_wr*ire()IMn2112;閂次ShlQft-U&tfrtiv9810.465野1-helJun2112;11shlotfi-Ubuntukernel;9B14.445449+hellc_flwd_ioctl()t)un211!:;33:11shlo-n-UbuntuIcernelt罪1土灰go+5Hltct?()|]un2112:shlan-Ubuntukernel;98ia.4?&i771.J>lnc^seiHELLOlun21121:31*11Ehla-n-Ubuntu:i泌-swltctiQ)un2]IS;Ehipn-UbLintiilee-r'flfll!如18.啪55迎-hBlltj_ffl&d_iecTl)1Jun2112:!3聚11Ehlo-n-U&LifituJee-rnel*9B10.fl655fi7+h&l)1Jun2112:mishlott-UbuntuIce-rni?!:[舞4?布6』|*SKltC?lO]un2112;:33:11srilon-Ubuntutcfrrnel:[筮1土465683]I>lnchinelunJI12;:33:11fihlon-Uburrtukernel:罪1土465713]-iwltch()Jun2112::33:115hla<i^Ubuntukernel:9BL&.4657S5|'he].lc_mDd_resd()!Jun2112::35t11shlon-Ubuntukernele9819.465911:|+heLlD_fflod_ioctl()1i)unai011sh

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論