游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Linux驱动基础篇hello驱动

  上一篇分享的:从单片机工程师的角度看嵌入式Linux中有简单提到Linux的三大类驱动:
  我们学习编程的时候都会从hello程序开始。同样的,学习Linux驱动我们也从最简单的hello驱动学起。驱动层和应用层
  还记得实习那会儿我第一次接触嵌入式Linux项目的时候,我的导师让我去学习项目的其它模块,然后尝试着写一个串口相关的应用。那时候知道可以把设备当做文件来操作,但是不知道为什么是这样,就去网上搜了一些代码(驱动代码),然后和我的应用代码放在同一个文件里。给导师看了之后,导师说那些驱动程序不需要我写,那些驱动已经写好被编译到内核里了,可以直接用了,我只需关注应用层就好了。我当时脑子里就在打转what?STM32用一个串口不就是串口初始化,然后想怎么用就怎么用吗?后来经过学习才知道原来是那么一回事呀。这就是单片机转转嵌入式Linux的思维误区之一。学嵌入式Linux之前我们有必要暂时忘了我们单片机的开发方式,重新梳理嵌入式Linux的开发流程。下面看一下STM32裸机开发与嵌入式Linux开发的一些区别:
  嵌入式Linux的开发方式与STM32裸机开发的方式有点不一样。在STM32的裸机开发中,驱动层与应用层的区分可能没有那么明显,常常都杂揉在一起。当然,有些很有水平的裸机程序分层分得还是很明显的。但是,在嵌入式Linux中,驱动和应用的分层是特别明显的,最直观的感受就是驱动程序是一个。c文件里,应用程序是另一个。c文件。比如我们这个hello驱动实验中,我们的驱动程序为hellodrv。c、应用程序为helloapp。c。驱动模块的加载有两种方式:第一种方式是动态加载的方式,即驱动程序与内核分开编译,在内核运行的过程中加载;第二种方式是静态加载的方式,即驱动程序与内核一同编译,在内核启动过程中加载驱动。在调试驱动阶段常常选用第一种方式,因为较为方便;在调试完成之后才采用第二种方式与内核一同编译。
  STM32裸机开发与嵌入式Linux开发还有一点不同的就是:STM32裸机开发最终要烧到板子的常常只有一个文件(除开含有IAP程序的情况或者其它情况),嵌入式Linux就需要分开编译、烧写。Linux字符设备驱动框架
  我们先看一个图:
  当我们的应用在调用open、close、write、read等函数时,为什么就能操控硬件设备。那是因为有驱动层在支撑着与硬件相关的操作,应用程序在调用打开、关闭、读、写等操作会触发相应的驱动层函数。
  本篇笔记我们以hello驱动做分享,hello驱动属于字符设备。实现的驱动函数大概是怎么样的是有套路可寻的,这个套路在内核文件includelinuxfs。h中,这个文件中有如下结构体:
  这个结构体里的成员都是些函数指针变量,我们需要根据实际的设备确定我们需要创建哪些驱动函数实体。比如我们的hello驱动的几个基本的函数(打开关闭读写)可创建为(以下代码来自:百问网):
  (1)打开操作staticinthellodrvopen(structinodenode,structfilefile){printk(sslined,FILE,FUNCTION,LINE);return0;}
  打开函数的两个形参的类型要与structfileoperations结构体里open成员的形参类型一致,里面有一句打印语句,方便直观地看到驱动的运行过程。
  (2)关闭操作staticinthellodrvclose(structinodenode,structfilefile){printk(sslined,FILE,FUNCTION,LINE);return0;}
  (3)读操作staticssizethellodrvread(structfilefile,charuserbuf,sizetsize,lofftoffset){interr;printk(sslined,FILE,FUNCTION,LINE);errcopytouser(buf,kernelbuf,MIN(1024,size));returnMIN(1024,size);}
  copytouser函数的原型为:staticinlineintcopytouser(voiduserto,constvoidfrom,unsignedlongn);
  用该函数来读取内核空间(kernelbuf)的数据给到用户空间(buf)。另外,kernelbuf的定义如下:staticcharkernelbuf〔1024〕;
  MIN为宏:defineMIN(a,b)(ab?a:b)
  把MIN(1024,size)作为copytouser的实参意在对拷贝的数据长度做限制(不能超出kernelbuf的大小)。
  (4)写操作staticssizethellodrvwrite(structfilefile,constcharuserbuf,sizetsize,lofftoffset){interr;printk(sslined,FILE,FUNCTION,LINE);errcopyfromuser(kernelbuf,buf,MIN(1024,size));returnMIN(1024,size);}
  copyfromuser函数的原型为:staticinlineintcopyfromuser(voidto,constvoiduservolatilefrom,unsignedlongn)
  用该函数来将用户空间(buf)的数据传送到内核空间(kernelbuf)。
  有了这些驱动函数,就可以给到一个structfileoperations类型的结构体变量hellodrv,如:staticstructfileoperationshellodrv{。ownerTHISMODULE,。openhellodrvopen,。readhellodrvread,。writehellodrvwrite,。releasehellodrvclose,};
  有些朋友可能没见过这种结构体初始化的形式(结构体成员前面加个。号),可以去看往期笔记:指定初始化器进行了解。
  上面这个结构体变量hellodrv容纳了我们hello设备的驱动接口,最终我们要把这个hellodrv注册给Linux内核,套路就是这样的:把驱动程序注册给内核,之后我们的应用程序就可以使用openclosewriteread等函数来操控我们的设备,Linux内核在这里起到一个中间人的作用,把两头的驱动与应用协调得很好。
  我们前面说了驱动的装载方式之一的动态装载:把驱动程序编译成模块,再动态装载。动态装载的体现就是开发板已经启动运行了Linux内核,我们通过开发板串口终端使用命令来装载驱动。装载驱动有两个命令,比如装载我们的hello驱动:方法一:insmodhellodrv。ko方法二:modprobehellodrv。ko
  其中modprobe命令不仅能装载当前驱动,而且还会同时装载与当前驱动相关的依赖驱动。有了转载就有卸载,也有两种方式:方法一:rmmodhellodrv。ko方法二:modproberhellodrv。ko
  其中modprobe命令不仅卸载当前驱动,也会同时卸载依赖驱动。
  我们在串口终端调用装载与卸载驱动的命令,怎么就会执行装载与卸载操作。对应到驱动程序里我们有如下两个函数:moduleinit(helloinit);注册模块加载函数moduleexit(helloexit);注册模块卸载函数
  这里加载与注册有用到helloinit、helloexit函数,我们前面说的把hellodrv驱动注册到内核就是在helloinit函数里做,如:staticintinithelloinit(void){interr;printk(sslined,FILE,FUNCTION,LINE);注册hello驱动majorregisterchrdev(0,主设备号,为0则系统自动分配hello,设备名称hellodrv);驱动程序下面操作是为了在dev目录中生成一个hello设备节点创建一个类helloclassclasscreate(THISMODULE,helloclass);errPTRERR(helloclass);if(ISERR(helloclass)){printk(sslined,FILE,FUNCTION,LINE);unregisterchrdev(major,hello);return1;}创建设备,该设备创建在helloclass类下面devicecreate(helloclass,NULL,MKDEV(major,0),NULL,hello);devhelloreturn0;}
  这里这个驱动程序入口函数helloinit中注册完驱动程序之后,同时通过下面连个创建操作来创建设备节点,即在dev目录下生成设备文件。据我了解,在之前版本的Linux内核中,设备节点需要手动创建,即通过创建节点命令mknod在dev目录下自己手动创建设备文件。既然已经有新的方式创建节点了,这里就不抠之前的内容了。
  以上就是分享关于驱动一些内容,通过以上分析,我们知道,其是有套路(就是常说的驱动框架)可寻的,比如:includelinuxmodule。hincludelinuxkernel。hincludelinuxinit。h其她头文件。。。。。。一些驱动函数staticssizetxxxread(structfilefile,charuserbuf,sizetsize,lofftoffset){}staticssizetxxxwrite(structfilefile,constcharuserbuf,sizetsize,lofftoffset){}staticintxxxopen(structinodenode,structfilefile){}staticintxxxclose(structinodenode,structfilefile){}其它驱动函数。。。。。。定义自己的驱动结构体staticstructfileoperationsxxxdrv{。ownerTHISMODULE,。openxxxopen,。readxxxread,。writexxxwrite,。releasexxxclose,其它程序。。。。。。。。。};驱动入口函数staticintinitxxxinit(void){}驱动出口函数staticvoidexithelloexit(void){}模块注册与卸载函数moduleinit(xxxinit);moduleexit(xxxexit);模块许可证(必选项)MODULELICENSE(GPL);
  按照这样的套路来开发驱动程序的,有套路可寻那就比较好学习了,至少不会想着怎么起函数名而烦恼,按套路来就好,哈哈
  关于驱动的知识,这篇笔记中还可以展开很多内容,限于篇幅就不展开了。我们之后再进行学习、分享。下面看一下测试程序应用程序(hellodrvtest。c中的内容,以下代码来自:百问网):includesystypes。hincludesysstat。hincludefcntl。hincludeunistd。hincludestdio。hincludestring。h。hellodrvtestwabc。hellodrvtestrintmain(intargc,charargv){intfd;charbuf〔1024〕;intlen;1。判断参数if(argc2){printf(Usage:swstring,argv〔0〕);printf(sr,argv〔0〕);return1;}2。打开文件fdopen(devhello,ORDWR);if(fd1){printf(cannotopenfiledevhello);return1;}3。写文件或读文件if((0strcmp(argv〔1〕,w))(argc3)){lenstrlen(argv〔2〕)1;lenlen1024?len:1024;write(fd,argv〔2〕,len);}else{lenread(fd,buf,1024);buf〔1023〕;printf(APPread:s,buf);}close(fd);return0;}
  就是一些读写操作,跟我们学习文件操作是一样的。学单片机的有些朋友可能不太熟悉main函数的这种写法:intmain(intargc,charargv)
  main函数在C中有好几种写法,在Linux中常用这种写法。argc与argv这两个值可以从终端(命令行)输入,因此这两个参数也被称为命令行参数。argc为命令行参数的个数,argv为字符串命令行参数的首地址。
  最后,我们把编译生成的驱动模块hellodrv。ko与应用程序hellodrvtest放到共享目录录nfsshare中,同时在开发板终端挂载共享目录:mounttnfsonolock,vers4192。168。1。104:homebooknfssharemnt
  关于nfs网络文件系统的使用可查看往期笔记:如何挂载网络文件系统?。
  然后我们通过insmod命令装载驱动,但是出现了如下错误:
  这是因为我们的驱动的编译依赖与内核版本,编译用的内核版本与当前开发板运行的内核的版本不一致所以会产生该错误,重新编译内核,并把编译生成的Linux内核zImage映像文件与设备树文件。dts文件拷贝到开发板根文件系统的boot目录下,然后进行同步操作:mounttnfsonolock,vers4192。168。1。114:homebooknfssharemntcpmntzImagebootcpmnt。dtbbootsync
  最后,重启开发板。最后,成功运行程序:
  下面是完整的hello驱动程序(来源:百问网):公众号:嵌入式大杂烩includelinuxmodule。hincludelinuxfs。hincludelinuxerrno。hincludelinuxmiscdevice。hincludelinuxkernel。hincludelinuxmajor。hincludelinuxmutex。hincludelinuxprocfs。hincludelinuxseqfile。hincludelinuxstat。hincludelinuxinit。hincludelinuxdevice。hincludelinuxtty。hincludelinuxkmod。hincludelinuxgfp。h1。确定主设备号staticintmajor0;staticcharkernelbuf〔1024〕;staticstructclasshelloclass;defineMIN(a,b)(ab?a:b)3。实现对应的openreadwrite等函数,填入fileoperations结构体staticssizethellodrvread(structfilefile,charuserbuf,sizetsize,lofftoffset){interr;printk(sslined,FILE,FUNCTION,LINE);errcopytouser(buf,kernelbuf,MIN(1024,size));returnMIN(1024,size);}staticssizethellodrvwrite(structfilefile,constcharuserbuf,sizetsize,lofftoffset){interr;printk(sslined,FILE,FUNCTION,LINE);errcopyfromuser(kernelbuf,buf,MIN(1024,size));returnMIN(1024,size);}staticinthellodrvopen(structinodenode,structfilefile){printk(sslined,FILE,FUNCTION,LINE);return0;}staticinthellodrvclose(structinodenode,structfilefile){printk(sslined,FILE,FUNCTION,LINE);return0;}2。定义自己的fileoperations结构体staticstructfileoperationshellodrv{。ownerTHISMODULE,。openhellodrvopen,。readhellodrvread,。writehellodrvwrite,。releasehellodrvclose,};4。把fileoperations结构体告诉内核:注册驱动程序5。谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数staticintinithelloinit(void){interr;printk(sslined,FILE,FUNCTION,LINE);majorregisterchrdev(0,hello,hellodrv);devhellohelloclassclasscreate(THISMODULE,helloclass);errPTRERR(helloclass);if(ISERR(helloclass)){printk(sslined,FILE,FUNCTION,LINE);unregisterchrdev(major,hello);return1;}devicecreate(helloclass,NULL,MKDEV(major,0),NULL,hello);devhelloreturn0;}6。有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数staticvoidexithelloexit(void){printk(sslined,FILE,FUNCTION,LINE);devicedestroy(helloclass,MKDEV(major,0));classdestroy(helloclass);unregisterchrdev(major,hello);}7。其他完善:提供设备信息,自动创建设备节点moduleinit(helloinit);moduleexit(helloexit);MODULELICENSE(GPL);
  嵌入式Linux的学习内容是很多的、坑也是很多的,死磕到底即可。
  1024G嵌入式资源大放送!包括但不限于CC、单片机、Linux等。私信回复1024,即可免费获取!

VR小姐姐扑面而来威联通TS453Bmini新体验换了这台TS453Bmini也很长一段时间了,这段时间也一直在折腾它,觉得是时候来写一写我对于这款NAS的使用感受,这个NAS真的是一款非常标准的4盘位NAS,除开最基本的数据……全球首款洗衣机器人亮相,松下洗护发布会创多项业内领先目前,中国家电市场已从早期的增量市场阶段,过渡至如今的存量市场时代。消费需求从单纯的购买转为替换,加之疫情带来的市场变革,种种因素都对企业综合能力提出了更高的要求。6月2……爱因斯坦的预言再次成真,物理学家首次看到黑洞后面反射的光天体物理学家检测到了来自黑洞远端的光,他们使用望远镜观测到了爱因斯坦广义相对论预言的、但尚未直接观测到的物理现象。新的发现证实了黑洞是如何扭曲光线的。一组研究人员最近检查……testflight安卓用户和ios用户的区别(老司机)前面几期的文章没想到很多(车友)一直问各种问题,本期我就摘个比较多人问的问题来解答图片来源微信公众号xo兄弟问题1:testflight的内测应用(老司机)ios端……干货你知道哪些国家原产地数据已经实现联网?你知道吗?中国海关可自助打印的原产地证书已经增加到16种了,那就意味着,有些证书,不用去跑窗口了!外贸资讯什么是原产地证书呢?就让我们来普及一下。原产地证明书……XC60卖得再好也不行?年销仅百的极星,让沃尔沃很尴尬文Lei如果真的要说哪个车企凭借收购某个高端品牌(而不是单纯的靠合资),彻底打开了自己品牌的高端化之路,那么吉利一定排得上号。2010年以18亿收购沃尔沃100股权……老婆说在聚餐,不方便接视频,还发来照片兄弟,你被绿了哈哈哈,老婆说在聚餐,不方便接视频,还发来照片兄弟,你被绿透了!!!兄弟带我和他女朋友见面,结果就这样了,大家说我该怎么办?有才说他一个四川的朋友借了他2万块钱,但……企业,如何通过大数据获客,精准营销截留客户大数据是一个数据信息的结合,根据一定的计算,可以寻找事情运作的规律性,体现一段时间内一件事情的主题活动发展趋势,是现代社会一种具备非常大使用价值的数据财产。一、大数据获客……质感至上,中兴Axon305G至臻版成下半年商务人士挚爱新机自从智能手机在市场上大行其道,让人离不开手后,各品牌手机商也开始针对目标人群做精准投放。比如专攻游戏玩家的游戏手机,喜欢展现自我的自拍手机,热衷听觉享受的音乐手机等,这些精准投……自然资源部59号通知矿山尾矿库地勘已列为重点监测对象近日,自然资源部办公厅发布关于近期加强安全生产工作有效防范化解重大安全风险的通知。通知指出,近期一些地方自然灾害和安全生产事故频发,造成重大人员伤亡和财产损失,教训十分深……豪车一定就贵吗?奥迪Q7对比岚图FREE,给出了不一样的答案对于能源时代的变革,不少业内人士评价这是自主品牌弯道超车的机会。但在我看来,弯道超车的目标太远,不是不能实现,只是需要时间。对自主品牌来说,能源时代的变革,更是提供了一次品牌向……5月7日,人生有时难免会陷入困境,但人的高贵在于,困境中依然5月7日每日简报,农历三月廿六,星期五!刷视频不如看看今天报告1、五一假期国内旅游出游2。3亿人次旅游收入1132。3亿元;五一假期全国揽投快递包裹近26亿件……
低碳减排迫在眉睫业内热议可持续金融存巨大结构性机遇财联社(北京,记者姜樊)讯,发展再生能源有两个关键点,一是大幅度的增加绿色投资;二是发展碳市场,处理好碳市场价格和能源价格的关系。今日,财政部原副部长朱光耀在第十六届21世纪亚……数字经济的底座新型数据中心的发展进阶之路当前,5G、云计算、人工智能等新一代信息技术快速发展,信息技术与传统产业加速融合,数字经济蓬勃发展。数据中心作为各个行业信息系统运行的物理载体,已成为经济社会不可或缺的关键基础……三星手机大面积系统崩溃,附解决方案前几天不少三星用户纷纷发现自己的手机出现了黑屏、系统崩溃、无法开机等现象,崩溃后的手机页面大概长这样看了下中招机型很多,三星GalaxyA系列如A60,三星S10、S20……小度估值200亿元!弯道超车后成智能家居市场赢家文杨剑勇前几天有消息指出小度将独立,今天百度官方宣布,小度完成独立融资,估值约200亿元,且百度公司继续保持拥有绝对控制权。笔者看来,小度独立融资,将实现独立发展,以内容……公务支出公款消费审计的八项经验分享笔者结合审计工作实践,就公务支出、公款消费审计的重点内容浅谈几点认识。一、进一步明确公务支出及公款消费审计的内容首先,根据相关要求,公务支出、公款消费的概念进一步明……区块链游戏开发者需要注意的4种攻击方式(下)在上一篇文章中,我们谈论了2种常见的区块链游戏攻击方式。接下来,我们将继续探讨2种需要区块链游戏开发者高度重视的漏洞。伪随机数漏洞对于区块链游戏开发者而言,无论以太……如果长津湖战役发生在现代,零下40度的战场,国产车顶得住吗长津湖战役是抗美援朝时期的第二次战役,是新中国志愿军与包括美国在内的联合国军之间的一场战役,最终以美国为首的联合国军撤退,新中国志愿军在东西两线同时大捷并收复了三八线以北的东部……丰田顶级旗舰轿车要入华?丰田国内悄悄注册ampampquot如果你了解日系豪华轿车的历史,那么你一定知道丰田世纪(CENTURY)这款车。世纪不仅是丰田公司社长丰田章男的座驾,更是天皇及日本本地成功企业家的最爱。就在最近,国内的商……美帝能源部将建造工业用重型燃料电池卡车美国能源部(D。O。E。)宣布,它打算投资1亿美元开发一种工业用重型燃料电池卡车。这些资金将用于帮助制定计划和建造H2汽车。这项为重型燃料电池卡车提供新资金的声明是……外贸行业站AxureRP原型编号:0172外贸行业站AxureRP原型版权说明:本站所有资料主要来源于网络的公开信息,都保留了原来的版权信息,本站所有的资料文档仅限用于学习交流,如若有侵权的嫌疑,请……家庭影院的真正意义是什么?打造家庭影院需要注意哪些问题?打造家庭影院的意义何在?刚接触家庭影院的时候,人们往往最先关注的是电影音效,要听现场感、包围感、追求低频能量扫库管的感觉等等。无论是商家和玩家,在给新人介绍的时候无不以此……国产文化IP备受追捧,文化产权保护进入新阶段近年来,随着大众对于传统文化的热情高涨,国潮产品、传统艺术品以新的面孔走进人们的生活,传统文化的创新成为一种新的潮流。与此同时,文化产品的版权问题也愈加受到人们的重视。在……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网