第1个linux驱动___整个系统是怎样工作的

接着上一篇博文中,我们已经在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驱动,你才有做好物联网的基础,未来将会是万物互联的时代,不光是手机、电脑、电视,你家里的冰箱、微波炉、台灯都会被接入互联网,这其中隐藏着巨大的商业价值,加油!

时间: 2024-10-31 15:54:25

第1个linux驱动___整个系统是怎样工作的的相关文章

第1个linux驱动___搭建环境,蓄势待发

如何开始写最简单的linux驱动? 在阅读本文前,你需要对linux的基本知识.ubuntu虚拟机的安装与命令行操作有基本的了解. 环境搭建:我在windows电脑上使用VMware打开安装好的虚拟机ubuntu9.0,ubuntu是运行linux内核的linux发行版. 我习惯secureCRT通过SSH远程登录到虚拟机上操作,当然你也可以直接在虚拟机环境下操作. 在根目录下建立一个目录树: cd / mkdir -p /work/my_drivers/frist_drv/1th 进入底层目录

第1个linux驱动___应用程序才是大Boss

我们的驱动模块已经可以被自动分配主设备号了,可以说到目前为止,一个驱动模块所具备的一些"基础设施"它都具备了,就像是养兵前日,用兵一时,已经可以让first_drv这个驱动模块出去打仗了. 那么说是出去打仗,总得有个发号施令的首长吧,在linux系统中,这位调兵遣将的首长就是应用程序,应用程序才是大Boss,我们"一直精雕细琢的驱动模块"说白了只是个跑腿的. 这就是为什么我们的专题是第1个linux驱动却要讲应用程序的原因,因为应用程序是让驱动程序能够被应用的,而驱

linux驱动之platform平台总线工作原理(一)

5.5.4.platform平台总线工作原理 5.5.4.1.何为平台总线 (1)platform总线相对于i2c.usb.spi.pci等总线是不同的,他们属于物理总线,platform总线是属于虚拟总线.抽象出来的,platform总线下的设备并不对应于真实存在的一种设备,这种总线在真实的物理是是没有的.比如i2c在物理上有i2c总线,但是platform总线在物理上并没有这种总线. (2)CPU和外部通信时,有两种连接方式,一种叫做地址总线式连接,一种叫做专用接口式连接,有一些设备是通过地

第1个linux驱动___打印"hello world"

为了方便后续的深入,我们在驱动程序中用printk( )函数来打印"hello world",printk( )是内核中自带的函数,专门用于在打印内核信息. 在安装驱动模块到内核中的时,需要进行驱动模块的初始化,初始化具体做什么我们先不提,我们暂时只用printk( )打印"hello world": int first_drv_init(void) { printk("hello world!\n"); return 0; } · 关于prin

第1个linux驱动___给驱动模块上户口

我们已经成功地通过开发板的最小根文件系统的/mnt目录挂接了虚拟机ubuntu的/work/my_drivers/ko_file目录下的内容,我们只要在最小根文件系统环境中执行:insmod /mnt/first_drv.ko,即可把ubuntu中编译好的first_drv.ko安装到开发板的内核中,卸载执行:rmmod first_drv或rmmod first_drv.ko即可. 下面,先来写一个方便我们挂接到虚拟机ubuntu的/work/my_drivers/ko_file的脚本,在最小

第1个linux驱动___编译空壳驱动程序

在上一篇博文中我们已经了解到整个系统中各个层次之间是如何协调如何工作的,应用层发出的命令经由内核下达到驱动层,从而达到操作硬件层的目的. 我们先回顾上上篇博文最后成型的"空壳驱动程序"first_drv.c中的代码: #include <linux/module.h> #include <linux/init.h> static int __init first_drv_init(void) {        printk(KERN_INFO"hell

第1个linux驱动___安装驱动模块之内核再爱我一次

在上一篇博文中,我们已经通过Makefile编译得到first_drv.ko文件,这是一个可以被安装到ubuntu中的驱动模块,要怎样做呢? 在/work/my_drivers/first_drv/1th/目录下执行:insmod first_drv.ko 如果你是在普通用户状态下执行的这条命令,可以看到系统提醒我们:insmod: error inserting 'first_drv.ko': -1 Operation not permitted 这是因为安装驱动模块需要超级权限,你可以在普通

第1个linux驱动___给驱动模块上户口(二)

从这篇博文开始,我们终于可以给我们的驱动模块first_drv一个正式的编制了,现在他已经填好了自己的户口登记信息表,距离拿户口本儿只有一步了! 内核内部有自己的一套安装驱动模块的方法,就像是民政局工作人员知道怎么给一个人办户口一样,对于一个普通公民来说,工作人员做了哪些操作办好了户口本,并不是普通公民需要关心的,我们最关心的是如何把我们填好的户口信息登记表交给工作人员,如何向工作人员表明我们有办户口的请求. 在linux系统中,对于字符设备驱动,我们通过register_chrdev这个函数来

第1个linux驱动___投靠NFS网络文件系统

之前我们一直是在虚拟机ubuntu环境中测试我们的first_drv驱动模块,但是这不是我们的开发方向,在刚开始的学习中我们避免搭建过多的环境,因此选择了只在ubuntu中测试驱动. 我们的模式是: [first_drv.c]-->[使用ubuntu内核源码编译]-->[first_drv.ko(可运行于虚拟机)]--> [ 安装到虚拟机中 ]-->[ hello world! ]-->[ 从虚拟机中卸载 ]-->[ goodbye world... ] 但是我们的最终