Linux驅(qū)動程序?qū)嵗齙第1頁
Linux驅(qū)動程序?qū)嵗齙第2頁
Linux驅(qū)動程序?qū)嵗齙第3頁
Linux驅(qū)動程序?qū)嵗齙第4頁
Linux驅(qū)動程序?qū)嵗齙第5頁
全文預(yù)覽已結(jié)束

下載本文檔

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

文檔簡介

1、最簡單的設(shè)備驅(qū)動程序hello.c#include<linux/init.h>#include<linux/module.h>MODULE_LICENSE("GPL");staticinthello_init(void)(printk(KERN_ALERT"Hello,Hello,LinuxDriver!\n");return0;}staticvoidhello_exit(void)(printk(KERN_ALERT"Goodbye,Hello,LinuxDriver!\n");}module_init(hello_init);module_exit(hello_exit);說明:⑴前兩行為所包含的頭文件,位于內(nèi)核源碼的目錄下include文件夾下的。(2)程序中的MODULE_LICENSE("GPL");用于聲明模塊的許可證。⑶module_init()為注冊加載時(shí)執(zhí)行的函數(shù),module_exit()為/注冊卸載時(shí)執(zhí)行的函數(shù)。傳遞給這兩個(gè)函數(shù)的的參數(shù)為所要進(jìn)行初始化的函數(shù)的地址(函數(shù)名)。模塊的編譯:使用gcc編譯器,與編譯普通程序不同的是要在參數(shù)-I后指定內(nèi)核源代碼的目錄,2.4的內(nèi)核模塊編譯后將生成.0格式的文件。命令行下的編譯格式如下:gcc-DMODULE-DKERNEL-I/usr/src/linux-2.4.20/include-chello.c其中-DMODULE-D__KERNEL__為兩個(gè)宏定義,如果文件中包含這兩個(gè)的宏定義,可以在gcc編譯時(shí)不用再指定。文件中宏定義的內(nèi)容如下:#ifndef__KERNEL_#define__KERNEL_#endif#ifndefMODULE#defineMODULE#endif模塊的加載與卸載模塊加載:在命令行下執(zhí)行:insmodhello.o。如果成功加載到內(nèi)核將在終端上顯示:Hello,Hello,LinuxDriver!。查看加載的模塊:通過lsmod命令可以查看內(nèi)核中已經(jīng)加載的模塊。模塊的卸載:rmmodhello.o。卸載成功的話將終端顯示:Goodbye,Hello,LinuxDriver!驅(qū)動模塊運(yùn)行在內(nèi)核空間,運(yùn)行時(shí)不能依賴于任何函數(shù)庫和模塊連接,所以在寫驅(qū)動時(shí)所調(diào)用的函數(shù)只能是作為內(nèi)核一部分的函數(shù)。內(nèi)核代碼不能實(shí)現(xiàn)浮點(diǎn)書運(yùn)算。2、一般驅(qū)動程序都會實(shí)現(xiàn)一個(gè)file_operation結(jié)構(gòu)中的函數(shù)。如test.c程序中所實(shí)現(xiàn)的file_operation結(jié)構(gòu)如下:

structfile_operationstest_fops={read:read_test,write:write_test,open:open_test,release:release_test,};該驅(qū)動程序所實(shí)現(xiàn)的功能是在內(nèi)存中開辟一段空間,write實(shí)現(xiàn)了往這段內(nèi)中寫數(shù)據(jù),read正好相反,是從這段內(nèi)存中讀出數(shù)據(jù)。(1)頭文件和全局變量定義如下:#include<linux/types.h>#include<linux/fs.h>#include<linux/mm.h>#include<linux/errno.h>#include<asm/segment.h>#include<asm/uaccess.h>#include<linux/module.h>#include<linux/version.h>#include<linux/config.h>MODULE_LICENSE("GPL");//設(shè)備號//存放內(nèi)存空間的指針//當(dāng)前內(nèi)存中擁有的數(shù)據(jù)的字節(jié)數(shù)unsignedinttest_major=254;char*str_test;unsignedintcount_driver;constunsignedintcount_driver_max=255;//容量的最大值(2)模塊初始化函數(shù)為://設(shè)備號//存放內(nèi)存空間的指針//當(dāng)前內(nèi)存中擁有的數(shù)據(jù)的字節(jié)數(shù)staticinttest_init_module(void){intresult;result=register_chrdev(test_major,"test",&test_fops);if(result<0){printk(KERN_INFO"test:can'tgetmajornumber\n");returnresult;}printk("registerok\n");if((str_test=(char*)kmalloc(256,GFP_KERNEL))==NULL)//申請256字節(jié)的內(nèi)存空間{printk("kmallocerror\n");return-1;Else(printk("kamllocsuccess!\n");count_driver=0;}return0;}完成了兩個(gè)工作:一、通過register_chrdev()向系統(tǒng)注冊了一個(gè)設(shè)備名為test的設(shè)備,設(shè)備號由test_major指定。應(yīng)用層對設(shè)備的操作方法由結(jié)構(gòu)test_fops中的指針?biāo)赶?。二、通過函數(shù)kmalloc()申請了一段256字節(jié)的內(nèi)存,用來存放應(yīng)用層用戶所寫的數(shù)據(jù)。⑶open和close的實(shí)現(xiàn),只是一個(gè)計(jì)數(shù)功能:staticintopen_test(structinode*inode,structfile*file)(MOD_INC_USE_COUNT;return0;}staticintrelease_test(structinode*inode,structfile*file)(MOD_DEC_USE_COUNT;return0;}(4)Write函數(shù)的實(shí)現(xiàn):staticssize_twrite_test(structfile*file,constchar*buf,size_tcount,loff_t*t)(intresult;if(count<count_driver_max)(if((result=copy_from_user(str_test,buf,count))==0)count_driver=count;elsecount_driver=0;}else(if((result=copy_from_user(str_test,buf,count_driver_max))==0)count_driver=count_driver_max;elsecount_driver=0;}returncountdriver;}它的功能是把用戶空間的數(shù)據(jù)復(fù)制到str_test所指的內(nèi)存空間中,復(fù)制數(shù)據(jù)前首先判斷數(shù)據(jù)的個(gè)數(shù)是不是內(nèi)存空間所能容納的,若是則直接復(fù)制,如果超出了count_driver_max,則只能復(fù)制count_driver_max個(gè)字節(jié)的數(shù)據(jù)。函數(shù)的返回值為成功復(fù)制數(shù)據(jù)的個(gè)數(shù):Read函數(shù)的實(shí)現(xiàn)staticssize_tread_test(structfile*file,char*buf,size_tcount,loff_t*t)(intresult,read_num;if(access_ok(VERIFY_WRITE,buf,count)==-EFAULT)return-EFAULT;printk("readstart!\n");if(count_driver>0)(if(count_driver>=count)(if((result=copy_to_user(buf,str_test,count))==0)read_num=count;elseread_num=0;}else(if((result=copy_to_user(buf,str_test,count_driver))==0)read_num=count_driver;elseread_num=0;}}elseread_num=0;returnread_num;}該函數(shù)的功能正好與write相反,從這段內(nèi)存空間中讀取數(shù)據(jù),當(dāng)讀取的數(shù)據(jù)個(gè)數(shù)不超過內(nèi)存中已存的數(shù)據(jù)個(gè)數(shù)時(shí)就直接復(fù)制,但當(dāng)超過時(shí),則只能復(fù)制內(nèi)存中已有的數(shù)據(jù)。函數(shù)返回值為成功讀取的數(shù)據(jù)的個(gè)數(shù)。將test.c文件通過gcc編譯后生成test.o模塊,通過insmod命令將其加載到內(nèi)核中。然后通過mknod命令在/dev目錄下創(chuàng)建設(shè)備節(jié)點(diǎn),如下所示的命令:gcc-DMODULE-DKERNEL-I/usr/src/linux-2.4.20/include-ctest.cinsmodtest.omknod/dev/testc2540c表示字符設(shè)備,254為主設(shè)備號,0為次設(shè)備號。為了測試驅(qū)動程序是否正常運(yùn)行,編寫了如下兩個(gè)程序:test_w.c和test_r.c.Test_w.c為:#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>intmain(void)(inti;inttestdev;intresult=2,resultr;charbuf[27]={'\0'};testdev=open("/dev/test",O_RDWR);if(testdev<0){printf("Cann'topenfile\n");return1;}printf("openok\n");buf[0]='a';for(i=1;i<26;i++)buf[i]=buf[0]+i;if((result=write(testdev,buf,26))<-1){printf("writefailed\n");return-1;}printf("writeintodriversuccess\nresult=%d,andthebuf=%s\n",result,buf);close(testdev);return0;}Test_r.c為:#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>intmain(void)inti;inttestdev;intresult;charbuf[27]={'\0'};testdev=open("/dev/test",O_RDWR);if(testdev<

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論