接着上一篇博文中,我们已经在first_drv.c中写好了空壳驱动程序。
但是编译这个空壳驱动程序之前,我们需要了解整个系统是怎么工作的。
不着急,首先,我们先来了解一点linux驱动的基本概念:
linux驱动分为字符设备驱动、块设备驱动、网络设备驱动。
这是按照驱动程序对不同的硬件的操作方式差异而划分的:
[ 字符设备驱动 ] 以字节级别的数据量来对硬件设备进行操作,涉及的硬件如:LED、LCD、串口、触摸屏等。
[ 块设备驱动 ] 则操作的数据量较大,如读写存储芯片的驱动就是块设备驱动,一次性要操作的数据往往涉及整个、数个扇区、块。涉及的硬件如:NandFlash、SD卡、U盘、硬盘等。
[ 网络设备驱动 ] 不同于字符设备驱动和快设备驱动,它是针对网卡设计的,对数据的操作往往是以网络的形式,网络设备驱动我还没有具体学习,以后学习到了会详细讲。
我们首先从字符设备驱动写起,那么我们要操作的硬件的首选是LED,因为这是最简单的硬件。
但是我们最初的驱动程序不宜涉及硬件操作,我们需要先了解linux系统的框架。
系统的分层从上至下可粗略地分为:
[ 应用层 ] --> 调用open( )、close( )等函数的可执行程序
[ API ] --> 各种库
[ 内核 ] --> 驱动程序可以认为与内核在同一层
[ 硬件 ] --> 底层硬件,如LED
打个比方,你要去北京,你可以骑自己的自行车去北京,可以骑三轮车去北京,可以开汽车去北京。好了,我们把这个例子深化一下:
现在你朋友(就是应用程序)给你(你自己就是内核)打电话叫你开三轮车去北京给他拉十几箱水果,那么朋友向你发出这个的请求就是向你调用了一辆三轮车,他向你发出了相当于是“掏钥匙去车库拿车”+ “启动三轮车开到北京去拉水果“这两个命令,在程序中就是应用程序调用了“open(你家的车库)”和”driver(三轮车)“,对你朋友而言,他并不知道你家车库在哪儿,但是他知道告诉你一个打开车库拿车这个请求(也就是open(车库)这个函数)你就会帮他拿到车。那么作为内核的你是怎样知道自己家的车库在哪儿的呢?因为这是你的家,你的车库是怎么修建起来的难道你毫不知情?你当然能够找到自家车库啦,毕竟你是有记忆的,那么问题来了,我们如何为内核构建这样一段记忆?
内核是这样做的,在内核中有一个file_operations结构体,你可以把这个结构体理解为"你自己随身携带的一本书",这本书上记着大量的信息,你通过翻阅file_operations这书就查到了上面记载的你家车库的地址,然后你知道了,只要出家门左转10米打开那个银色卷闸门里面就是车库了,三轮车就停在里面呢。
或者我们把朋友打来的那个电话改成:让你去打开小红家的车库拿辆三轮车,你肯定一脸懵逼,我特么哪儿知道小红是谁?更不知道小红家的车库在哪儿,怎么给你拿车?但是如果你手中那本file_operations书上写着小红家车库地址:“xx市xx区xx街道xx号旁的白色车库,车库钥匙在车库门口的地毯下。”如果是这样我相信就算你是傻瓜你也能通过file_operations这本书的指示打开小红家的车库了。
当然上面的例子虽然简单但有些不完美,毕竟开三轮车去北京拉水果的人不能是内核,“打开车库、安排司机开走”这才是内核的工作,应该额外安排一名司机把三轮车开走,这名司机掌握着驱动车辆的技能,知道朝哪个行驶,也就是说司机才是驱动,内核不能是驱动,下面我们来正式地举一个适合于linux系统工作方式的例子:
我们来试想一下,你是一名车辆管理员,你有三辆车:自行车、三轮车、汽车,你有一个老板,在你头顶上处处压制你、成天使唤你,每天就是叫你把三辆车分别交给三位司机,他们分别叫做张三、李四还有王二,你老板还让你转告这三位司机:张三,你今天把自行车骑到河边卖小红花去,2小时候后回来还车;李四,你今天骑三轮车去市场拉水果,注意不能把车厢弄脏了,下午还车;王二,你今天开汽车去外地接个客人,一定得把驾驶证带好,天黑前必须回这儿还车,这样,这三位司机就被局限在你老板所要求的这些条条框框之中,他们才是社会中最底层的人,而你在中间只是充当一个“为老板管理他们、调度他们”的角色罢了,如果你的老板不给你下达命令,你可能就成了一个无所事事的人,相反,如果你能够每天按时派车给三位司机,在规定时间收回车钥匙,那么老板能赚钱,你也能拿到工资,养家糊口。
在这个例子中,老板是应用程序(app),你车辆管理员是内核(kernel),三位客人都是驱动程序(driver),司机们工作所使用的三辆车则是硬件设备(hardware)。
但是在整个系统中,事实还更为残酷,老板总是下发无穷无尽的任务给你,而你只能永远机器式地满足老板的要求,而且拿不到任何报酬,三位司机更难过,空有一身驾车才华,却只能按照老板的意思行事,老板叫你往在城东开你就不能在城西开,一会儿叫你拉水果一会叫你运包裹,必须随时按老板的意思去工作,而且钱都归老板,车辆只会越来越老旧,甚至损坏,当车辆都损坏了,老板也就不敢唱高调、成天去差使谁了,因为车都用不了啦,他没有了谋生的路子,大家就都完了,解脱了。
这个例子有点类似于当年日本政府在东北建立了伪满洲国,日本政府就相当于应用层,在伪满洲国拥有至高无上的权力,而溥仪皇帝就是内核,但只是一个傀儡,对上讨好日伪,对下压迫百姓,而底层驱动就是黎民百姓,整天被奴役,被迫在满目疮痍的土地(也就是硬件层)上劳作,然后日本政府看到了这样的伪满洲国就感到很高兴,很满意,因为这样为他们日本创造了很多价值和财富。
linux系统也是如此,但好在内部的每个层次都是程序与硬件相配合完成的,都是无生命的,自然不会有任何怨言,因此,我们尽管写好上层应用和底层驱动,来实现想要的功能,创造出无尽的价值和财富。
也想以这个例子告诉大家,用我们的技术帮助中国变得更加强大,让历史不再重演,实现中华民族的伟大复兴!
这不仅仅是说说而已,如果你也是程序员,那么你就知道程序员是拥有创造的能力的,试问还有哪个行业的人员能像程序员这样能自由而快速地实现自己的想法的?我们想让LED点亮就点亮,想在LCD上显示啥就显示啥,我们能够通过代码把自己虚拟的想法变为现实中实际存在的东西,这是一件很酷的事情,通过代码让一块电路板运行起来,让一台机器工作起来,把自己的想法注入到没有生命的硬件中,让它们为我们服务,这还不够酷吗?
在精神世界中,上帝就是皇帝,在现实世界中,皇帝就是皇帝,在虚拟世界中,程序员才是皇帝。
学好linux驱动,你才有做好物联网的基础,未来将会是万物互联的时代,不光是手机、电脑、电视,你家里的冰箱、微波炉、台灯都会被接入互联网,这其中隐藏着巨大的商业价值,加油!