linux驱动编写(虚拟字符设备编写)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
---------------------------------------------------------------最新资料推荐------------------------------------------------------ linux驱动编写(虚拟字符设备编写)
linux 驱动编写(虚拟字符设备编写)昨天我们说了一些简单模块编写方法,但是终归没有涉及到设备的编写内容,今天我们就可以了解一下相关方面的内容,并且用一个实例来说明在 linux 上面设备是如何编写的。
虽然我不是专门做 linux 驱动的,却也经常收到一些朋友们的来信。
在信件中,很多做驱动的朋友对自己的工作不是很满意,认为自己的工作就是把代码拷贝来拷贝去,或者说是改来改去,没有什么技术含量。
有这种想法的朋友不在少数,我想这主要还是因为他们对自己的工作缺少了解导致。
如果有可能,我们可以问问自己这样几个问题:
(1 )我真的搞懂设备的开发驱动流程了吗?我是否可以从0开始,编写一个独立的驱动代码呢?(2)我真的了解设备的初始化、关闭、运行的流程吗?(3)当前的设备驱动流程是否合理,有没有可以改进的地方?(4)对于内核开发中涉及的 api 调用,我自己是否真正了解、是否明白它们在使用上有什么区别?(5)如果我要驱动的设备只是在一个前后台系统中运行,在没有框架帮助的情况下,我是否有信心把它启动和运行起来?当然,上面的内容只是我个人的想法,
1/ 6
也不一定都正确。
但是,知其然,更要知其所以然,熟悉了当前开发流程的优缺点才能真正掌握和了解驱动开发的本质。
这听上去有些玄乎,其实也很简单,就是要有一种刨根问底、不断改进的精神,这样才能做好自己的工作。
因为我们是在 pc linux 上学习驱动的,因此暂时没有真实的外接设备可以使用,但是这丝毫不影响我们学习的热情。
通过定时器、进程,我们可以仿真出真实设备的各种需求,所以对于系统来说,它是无所谓真设备、假设备的,基本的处理流程对它来说都是一样的。
只要大家一步一步做下去,肯定可以了解 linux 驱动设备的开发工程的。
下面,为了说明问题,我们可以编写一段简单的 char 设备驱动代码,文件名为 char.c,#includelinux/module. h#includelinux/kernel. h#includelinux/fs.h
#includelinux/cdev.h staticstructcdevchr_dev; staticdev_tndev;
staticintchr_open(structinode*nd,structfile*filp){ intmajor;intminor;
major=MAJOR(nd‐i_rdev);minor=MINOR(nd‐i_rdev);
printk(chr_open,major=%d,minor=%d\n, major, minor); return0; }
---------------------------------------------------------------最新资料推荐------------------------------------------------------ staticssize_tchr_read(structfile*filp,char__user*u,size_tsz
,loff_t*off){printk(chr_readprocess! \n); return0; }
structfile_operationschr_ops={.owner=THIS_MODULE, .open=chr_open, .read=chr_read }; staticintdemo_init(void){intret;
cdev_init(chr_dev,chr_ops);
ret=alloc_chrdev_region(ndev,0, 1,chr_dev);if(ret0)
{ returnret; } printk(demo_init():major=%d, minor=%d\n,MAJOR(ndev),MINOR(ndev));
ret=cdev_add(chr_dev,ndev,1);if(ret0){ returnret;}return0; } staticvoiddemo_exit(void){printk(demo_exitprocess! \n); cdev_del(chr_dev); unregister_chrdev_region(ndev,1);}
module_init(demo_init);module_exit(demo_exit);
MODULE_LICENSE(GPL);MODULE_AUTHOR(feixiaoxing@);
MODULE_DESCRIPTION(Asimpledeviceexample! ); 过程就全部完成了,就是这么简单。
当然为了编写这个文件,我们还需要编写一个 Makefile 文件,[ cpp] view plaincopy ifneq($(KERNELRELEASE), )
3/ 6
obj‐m: =char. o else PWD:=$(shellpwd)KVER:
=$(shelluname‐r) KDIR: =/lib/modules/$(KVER)/build
all:$(MAKE)‐C$(KDIR)M=$(PWD)modules clean:
rm‐rf.*.
cmd*.o*.mod.c*.ko.tmp_versionsmodules.*Module.* endif经
加入到系统当中,完全可以通过输入 lsmod | grep char 进行查找
和验证。
为了创建设备节点,我们需要知道设备为我们创建的 major、minor 数值是多少,所以 dmesg | tail 查找一下数值。
在我 hp的机器上,这两个数值分别是249和0,所以下面可
以利用它们直接创建设备节点了,输入mknod /dev/chr_dev c 249
0即可,此时可以输入 ls /dev/chr_dev 验证一下。
那么,按照这种方法,真的可以访问这个虚拟设备了吗,我
们可以编写一段简单的代码验证一下, [ cpp] view plaincopy #includestdio.h#includefcntl.h
#includeunistd.h
#defineCHAR_DEV_NAME/dev/chr_dev intmain() {intret;intfd;charbuf[32];
fd=open(CHAR_DEV_NAME,O_RDONLY| O_NDELAY);if(fd0)
{ printf(openfailed! \n);return‐1; }
read(fd,buf,32);close(fd);return0; } 代码的内容非常简单,就是利用 CHAR_DEV_NAME 直接打开设备,读