您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > Linux字符设备驱动程序实验
实验九:Linux字符设备驱动程序实验实验目的:1.理解Linux设备驱动程序的基本原理;2.掌握Linux字符设备驱动程序的框架结构;3.学会编写字符设备驱动程序。实验设备:PC机。实验原理:Linux函数(系统调用)是应用程序和操作系统内核之间的接口,而设备驱动程序是内核和硬件设备之间的接口,设备驱动程序屏蔽硬件细节,且设备被映射成特殊的文件进行处理。每个设备都对应一个文件名,在内核中也对应一个索引节点,应用程序可以通过设备的文件名来访问硬件设备。Linux为文件和设备提供了一个致性的接口,用户操作设备文件与操作普通文件类似。例如,通过open()函数可打开设备文件,建立起应用程序与目标设备的连接;之后,可以通过read()、write()、ioctl()等常规文件函数对目标设备进行操作。实验方法:实现对虚拟设备(一段内在)的打开、关闭、读写的操作,并要通过编写测试程序来测试虚拟设备及其驱动运行是否正常。1.实验源代码/*test_drv.c*/#includelinux/module.h#includelinux/init.h#includelinux/fs.h#includelinux/kernel.h#includelinux/slab.h#includelinux/types.h#includelinux/errno.h#includelinux/cdev.h#includeasm/uaccess.h#defineTEST_DEVICE_NAMEtest_dev#defineBUFF_SZ1024/*全局变量*/staticstructcdevtest_dev;unsignedintmajor=0;staticchar*data=NULL;/*函数声明*/staticssize_ttest_read(structfile*file,char*buf,size_tcount,loff_t*f_pos);staticssize_ttest_write(structfile*file,constchar*buffer,size_tcount,loff_t*f_pos);staticinttest_open(structinode*inode,structfile*file);staticinttest_release(structinode*inode,structfile*file);/*读函数*/staticssize_ttest_read(structfile*file,char*buf,size_tcount,loff_t*f_pos){intlen;if(count0){return-EINVAL;}len=strlen(data);count=(lencount)?count:len;if(copy_to_user(buf,data,count)){return-EFAULT;}returncount;}/*写函数*/staticssize_ttest_write(structfile*file,constchar*buffer,size_tcount,loff_t*f_pos){if(count0){return-EINVAL;}memset(data,0,BUFF_SZ);count=(BUFF_SZcount)?count:BUFF_SZ;if(copy_from_user(data,buffer,count)){return-EFAULT;}returncount;}/*打开函数*/staticinttest_open(structinode*inode,structfile*file){printk(Thisisopenoperation\n);data=(char*)kmalloc(sizeof(char)*BUFF_SZ,GFP_KERNEL);if(!data){return-ENOMEM;}memset(data,0,BUFF_SZ);return0;}/*关闭函数*/staticinttest_release(structinode*inode,structfile*file){printk(Thisisreleaseoperation\n);if(data){kfree(data);data=NULL;}return0;}staticvoidtest_setup_cdev(structcdev*dev,intminor,structfile_operations*fops){interr,devno=MKDEV(major,minor);cdev_init(dev,fops);dev-owner=THIS_MODULE;dev-ops=fops;err=cdev_add(dev,devno,1);if(err){printk(KERN_NOTICEError%daddingtest%d,err,minor);}}/*tests设备的file_operations结构*/staticstructfile_operationstest_fops={.owner=THIS_MODULE,.read=test_read,.write=test_write,.open=test_open,.release=test_release,};/*模块注册入口*/intinit_module(void){intresult;dev_tdev=MKDEV(major,0);if(major){result=register_chrdev_region(dev,1,TEST_DEVICE_NAME);}else{result=alloc_chrdev_region(&dev,0,1,TEST_DEVICE_NAME);major=MAJOR(dev);}if(result0){printk(KERN_WARNINGTestdevice:unabletogetmajor%d\n,major);returnresult;}test_setup_cdev(&test_dev,0,&test_fops);printk(Themajorofthetestdeviceis%d\n,major);return0;}/*卸载模块*/voidcleanup_module(void){cdev_del(&test_dev);unregister_chrdev_region(MKDEV(major,0),1);printk(Testdeviceuninstalled\n);}2.参考Makefile文件ifeq($(KERNELRELEASE),)KERNELDIR?=/lib/modules/$(shelluname-r)/buildPWD:=$(shellpwd)modules:$(MAKE)-C$(KERNELDIR)M=$(PWD)modulesmodules_install:$(MAKE)-C$(KERNELDIR)M=$(PWD)modules_installclean:rm-rf*.o*~core.depend.*.cmd*.ko*.mod.c.tmp_versions.PHONY:modulesmodules_installcleanelseobj-m:=test_drv.oendif3.参考加载驱动模块的脚本文件#!/bin/shmodule=test_drvdevice=test_devmode=664group=lmx#removestalenodesrm-f/dev/${device}#invokeinsmodwithallargumentswegot#anduseapathname,asnewermodutilsdon'tlookin.bydefault/sbin/insmod-f./$module.ko$*||exit1major=`cat/proc/devices|awk\\$2==\$device\{print\\$1}`mknod/dev/${device}c$major0#giveappropriategroup/permissionschgrp$group/dev/${device}chmod$mode/dev/${device}4.参考卸载驱动模块的脚本文件#!/bin/shmodule=test_drvdevice=test_dev#invokermmodwithallargumentswegot/sbin/rmmod$module$*||exit1#removenodesrm-f/dev/${device}exit05.参考测试代码/*test.c*/#includestdio.h#includestdlib.h#includestring.h#includesys/stat.h#includesys/types.h#includeunistd.h#includefcntl.h#defineTEST_DEVICE_FILENAME/dev/test_dev#defineBUFF_SZ1024intmain(){intfd,nwrite,nread;charbuff[BUFF_SZ];fd=open(TEST_DEVICE_FILENAME,O_RDWR);if(fd0){perror(open);exit(1);}do{printf(Inputsomewordstokernel(enter'quit'toexit):);memset(buff,0,BUFF_SZ);if(fgets(buff,BUFF_SZ,stdin)==NULL){perror(fgets);break;}buff[strlen(buff)-1]='\0';if(write(fd,buff,strlen(buff))0){perror(write);break;}if(read(fd,buff,BUFF_SZ)0){perror(read);break;}else{printf(Thereadstringisfromkernel:%s\n,buff);}}while(strncmp(buff,quit,4));close(fd);exit(0);}6.首先在虚拟设备驱动源码目录下编译并加载驱动模块#makeclean#make#./test_drv_load7.编译并运行测试程序,然后查看测试结果#gcc-otesttest.c#./test8.卸载驱动程序#./test_drv_unload9.通过dmesg命令可以查看内核打印的信息实验结果:学会和掌握Linux字符设备驱动程序的编写和测试等。
本文标题:Linux字符设备驱动程序实验
链接地址:https://www.777doc.com/doc-5095419 .html