解答来自知乎:https://www.zhihu.com/question/22175660
================================================================================================================================
作者:时国怀
链接:https://www.zhihu.com/question/22175660/answer/20547502来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。驱动和固件(firmware)都是代码,前者为软件服务,后者为硬件服务。
在操作系统概念还不明确的时代,二者是没有明显区别的。
但是随着计算机体系结构的发展,硬件的种类开始变多,操作系统的种类也变多了。
这个时候,因为各种技术的、商业的原因,硬件厂商希望自己的硬件能被更多的软件厂商使用,所以就需要在硬件之上做一些封装,让自己的硬件操纵起来更容易,这个时候就要有firmware这种东西了,它简化了软件与硬件的交互。
但是为什么不把fimware做的很完美,做的不需要驱动支持呢?因为有不同的操作系统。我不知道你对操作系统的理解是到什么程度?只知道Windows?还是还仅仅知道Linux?还是清楚Unix和FreeBSD是不同的系统?知道有RTOS?知道有上百种不同的内核?
不同的操作系统,对于操作硬件的方式完全不同,在Windows里应用态是无法直接写IO端口的,而在嵌入式系统里,一般都不限制直接操作IO端口。所以,硬件厂商一方面为了自己的硬件能被软件更简单的使用,就需要写firmware,而另一方面为了兼容各种操作系统,又不能把firmware写的太死,必须预留足够的余地让软件自由发挥——软件的自由发挥就是驱动。
不同操作系统的驱动是不能兼容的,原因就是驱动是为操作系统服务的,有的操作系统是单线程的,有些操作系统不允许动态申请内存,所以不同的操作系统要操作硬件,就要根据自身的特性编写对应的操作代码,这就是驱动存在的意义——适应系统需要。
假如世界上只有一种操作系统,并且版本永远不会改变,那么firmware和驱动就可以融合在一起,但这只能一个不现实的梦想,要知道民用操作系统和工业控制操作系统差别是十分巨大的。从计算机领域来说,驱动和固件从来没有过明确的定义,就好像今天我们说内存,大部分人用来表示SDRAM,但也有人把Android里的“固化的Flash/Storage"称为“内存”,你不能说这样说就错了,因为这确实是一种“内部存储”。
但在Linux Kernel中,Driver和Firmware是有明确含义的,其中Driver是控制被操作系统管理的外部设备(Device)的代码段。很多时候Driver会被实现为LKM,但这不是必要条件。driver通过driver_register()注册到总线(bus_type)上,代表系统具备了驱动某种设备(device)的能力。当某个device被注册到同样的总线的时候(通常是总线枚举的时候发现了这个设备),总线驱动会对driver和device会通过一定的策略进行binding(即进行匹配),如果Binding成功,总线驱动会调用driver的probe()函数,把设备的信息(例如端口,中断号等)传递给驱动,驱动就可以对真实的物理部件进行初始化,并把对该设备的控制接口注册到Linux的其他子系统上(例如字符设备,v4l2子系统等)。这样操作系统的其他部分就可以通过这些通用的接口来访问设备了。
而Firmware,是表示运行在非“控制处理器”(指不直接运行操作系统的处理器,例如外设中的处理器,或者被用于bare metal的主处理器的其中一些核)中的程序。这些程序很多时候使用和操作系统所运行的处理器完全不同的指令集。这些程序以二进制形式存在于Linux内核的源代码树中,生成目标系统的时候,通常拷贝在/lib/firmware目录下。当driver对device进行初始化的时候,通过request_firmware()等接口,在一个用户态helper程序的帮助下,可以把指定的firmware加载到内存中,由驱动传输到指定的设备上。
所以,总的来说,其实driver和firmware没有什么直接的关系,但firmware通常由驱动去加载。我们讨论的那个OS,一般不需要理解firmware是什么,只是把它当做数据。firmware是什么,只有使用这些数据的那个设备才知道。好比你用一个电话,电话中有一个软件,这个软件你完全不关心如何工作的,你换这个软件的时候,就可以叫这个软件是“固件”,但如果你用了一个智能手机,你要细细关系什么是上面的应用程序,Android平台,插件之类的细节内容,你可能就不叫这个东西叫“固件”了。
这种情况在计算机领域非常常见,所以大部分Spec都自己重新定义概念。比如说,我们平时写软件,说Component,很多就是只软件的其中一个部分,但在UEFI中,Component的定义是:
An executable image. Components defined in this specification support on elf the defined module types.
这是一个“独立的映像”,和我们一般理解的概念就完全不同,但如果你学计算机,请了解,这是我们的惯例。driver 和 firmware 两个名词有很大的区别。
驱动 driver 指的提供编程api接口,用以操控某一硬件/软件产品的应用程序。以程序的使用目的来定义 它是否为driver。
固件firmware 概念上来说是指那些预安装到硬件产品内部只读记忆体里面,与硬件产品捆绑匹配的程序。这个名词的定义主要强调此类软件的不应当被修改,并且与硬件捆绑的特性。更改firmware属于hack范畴了。
名词解释到这,下面举几个例子吧
属于driver但是不属于firmware的例子:
1. oracle database, .net driver。 所有软件产品的驱动都不属于固件。
2. 打印机 驱动光盘。由于并没有预装入打印机只读记忆体,不属于固件。
属于固件但不属于驱动的:
1. 洗衣机内置电脑程序。此为直接用户交互的系统终端(user interface,UI),并不和其他应用程序交互(application programming interface, API).
2. 计算器里面的操作系统。
同属于firmware 和 driver的 1. 路由器内置系统... 刻录入路由器存储器,用于与其他软件连接交互的(电脑,手机,其他路由器等)