




已阅读5页,还剩19页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
如果你对内核驱动模块一无所知,请先学习内核驱动模块的基础知识。如果你已经入门了内核驱动模块,但是仍感觉有些模糊,不能从整体来了解一个内核驱动模块的结构,请赏读一下这篇拙文。如果你已经从事内核模块编程N年,并且道行高深,也请不吝赐教一下文中的疏漏错误。本文中我将实现一个简单的Linux字符设备,旨在大致勾勒出linux内核模块的编写方法的轮廓。其中重点介绍ioctl的用途。我把这个简单的Linux字符设备模块命名为hello_mod.设备类型名为hello_class设备名为hello该设备是一个虚拟设备,模块加载时会在/sys/class/中创建名为hello_class的逻辑设备,在/dev/中创建hello的物理设备文件。模块名为hello_mod,可接受输入字符串数据(长度小于128),处理该输入字符串之后可向外输出字符串。并且可以接受ioctl()函数控制内部处理字符串的方式。例如:a.通过write函数写入 “Tom”,通过ioctl函数设置langtype=chinese,通过read函数读出的数据将会是“你好!Tom/n”b.通过write函数写入 “Tom”,通过ioctl函数设置langtype=english,通过read函数读出的数据将会是“hello!Tom/n”c.通过write函数写入 “Tom”,通过ioctl函数设置langtype=pinyin,通过read函数读出的数据将会是“ni hao!Tom/n”一般的内核模块中不会负责设备类别和节点的创建,我们在编译完之后会得到.o或者.ko文件,然后insmod之后需要mknod来创建相应文件,这个简单的例子中我们让驱动模块加载时负责自动创建设备类别和设备文件。这个功能有两个步骤,1)创建设备类别文件 class_create();2)创建设备文件 device_create();关于这两个函数的使用方法请参阅其他资料。linux设备驱动的编写相对windows编程来说更容易理解一点因为不需要处理IRP,应用层函数和内核函数的关联方式浅显易懂。比如当应曾函数对我的设备调用了open()函数,而最终这个应用层函数会调用我的设备中的自定义open()函数,这个函数要怎么写呢,我在我的设备中定义的函数名是hello_mod_open,注意函数名是可以随意定义,但是函数签名是要符合内核要求的,具体的定义是怎么样请看static int hello_mod_open(struct inode *, struct file *);这样就定义了内核中的open函数,这只是定义还需要与我们自己的模块关联起来,这就要用到一个结构struct file_operations这个结构里面的成员是对应于设备操作的各种函数的指针。我在设备中用到了这些函数所以就如下定义,注意下面的写法不是标准ANSI C的语法,而是GNU扩展语法。struct file_operations hello_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,;这个结构体变量定义好之后我们在模块初始化函数中就可以通过register_chrdev()或者填充cdev结构来关联所有的操作到我们的模块函数了。和设备交互的数据我们总称为“数据”,但是大致可划分为两种“功能数据”:我们要输入设备处理的和设备处理完之后输出的数据。“控制数据”:我们用来控制设备特性功能的命令和参数。open,read,write,release等函数是对一个驱动模块的使用,就是我们对“设备的功能”的使用。但是一个设备有可能有很多功能,那么我们要怎么控制设备让设备完成指定的功能呢?据个例子来说:假如我们有一个翻译机(姑且说机吧,也可能是器)实体设备,主要功能是输入中文,然后可以输出各种语言对应的翻译结果,那这个机的功能就是翻译,我们真正用来处理的数据是我们输入的中文,我们要得到的“设备功能”就是翻译后的输出内容,而各种语言则是我们的选择控制了,我们可设定这个设备翻译成何种语言。这就要求我们要向设备发送命令,设定目标语言。请注意我们要发送的是两个“控制数据”,命令和参数。命令:一个设备可能有很多种行为,我们的命令就是代表我们要让设备执行何种行为。“复位”,“设定目标语言”,“获得当前目标语言”等参数:对于某一个命令,可能需要参数可能不需要参数。 比如:“复位”命令就不需要参数。 “设定目标语言”则需要传入目标语言的类型。 “获取目标语言”则需要传入一个能够接收目标语言类型的参数。自己画了一个设备“数据流”图,希望能加深理解。对于我们自己的设备我们就要自己定义设备命令了,如果你要想搞清命令的格式,请参考其他资料关于ioctl的参数的介绍。这里不打算介绍这个,只介绍ioctl实际功能。定义自己的IO控制命令需要用到宏。这里直接写出我的定义而不是介绍宏的实现#define HELLO_MAGIC12#define HELLO_IOCTL_RESETLANG_IO(HELLO_MAGIC,0)/设置复位,这个命令不带参数#define HELLO_IOCTL_GETLANG_IOR(HELLO_MAGIC,1,int)/获取当前设备的语言类型参数,参数是int型#define HELLO_IOCTL_SETLANG_IOW(HELLO_MAGIC,2,int)/设置设备的语言类型,参数是int型多的不说了,下面贴上完整代码,懒人没写注释。不好意思。hello_mod.ccpp view plaincopyprint?/*=*Filename:hello.c*Description:hello_mod*Version:1.0*Created:01/28/201105:07:55PM*Revision:none*Compiler:gcc*Author:Tishion(shion),*Company:LIM*=*/#include #include #include #include #include #include #include #include #include #include #include #include #includehello_mod_ioctl.h #defineMAJOR_NUM250 #defineMINOR_NUM0 #defineIN_BUF_LEN256 #defineOUT_BUF_LEN512 MODULE_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);return-EBUSY;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)return-ERESTARTSYS;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,你好!%s.,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);return-EFAULT;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)return-ERESTARTSYS;if(lenIN_BUF_LEN)printk(Outofinputbuffer/n);return-ERESTARTSYS;if(copy_from_user(inbuffer,user_buf,len)up(&sem);return-EFAULT;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(result0)printk(hello_mod:cantgetmajornumber!/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().Pleaseexecmknodbeforeoperatethedevice/n);elsedevice_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.hcpp view plaincopyprint?/*=*Filename:hello_mod_ioctl.h*Description:definethecmdsupportedbyhello_mod*Version:1.0*Created:06/19/201110:24:20PM*Revision:none*Compiler:gcc*Author:Tishion(shion),*Company:LIM*=*/#ifndef_HELLO_MOD_IOCTL_H_ #define_HELLO_MOD_IOCTL_H_ #defineHELLO_MAGIC12 #defineHELLO_IOCTL_RESETLANG_IO(HELLO_MAGIC,0)/setlangtype=english #defineHELLO_IOCTL_GETLANG_IOR(HELLO_MAGIC,1,int)/getlangtype #defineHELLO_IOCTL_SETLANG_IOW(HELLO_MAGIC,2,int)/setlangtype typedefenum_lang_tenglish,chinese,pinyinlang_t;#endifMakefile#* #Makefilelinux2.6Module #ThismakefileiswrittenforUbuntu10.10 #Itmaynotperfomancewithouterrosonthe #otherversionordistributions. #* #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附上一用户层测试文件
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 财务管理标准化报告与财务分析模板
- 2025年教师招聘之《幼儿教师招聘》模拟试题含答案详解(突破训练)
- 雨的自述作文500字7篇
- 客户需求分析问卷标准化模板
- 教师招聘之《幼儿教师招聘》能力提升打印大全及参考答案详解【考试直接用】
- 2025年教师招聘之《小学教师招聘》考前冲刺练习题及完整答案详解【考点梳理】
- 可再生能源产业项目合作合同
- 策划春节联欢会方案模板
- 2025年教师招聘之《小学教师招聘》通关试题库含完整答案详解(各地真题)
- 耐火厂安全生产培训内容课件
- 欧盟职业教育数字素养培育研究
- 2025届河南省五市高三第一次联考生物试题(原卷版+解析版)
- T-BSRS 128-2024 核医学放射性废液快速处理技术要求
- 《血小板功能障碍与血栓形成》课件
- 《融资攻略》课件
- TCTBA 005-2024 TCECA-G 0326-2024 合同能源管理招标规范 轨道交通
- 工勤岗转管理岗申请书
- 特种设备定期检验与维护管理
- 《陕西省分布的国家重点保护野生植物名录》
- 2025年国网数科控股公司招聘高校毕业生37人(第一批)高频重点提升(共500题)附带答案详解
- 食管肿瘤护理查房
评论
0/150
提交评论