驱动是什么东西?为什么需要驱动?
从计算机的眼睛里看,设备就是一组寄存器,比如说IO设备, 串口,键盘,磁盘,打印机,总线,中断控制器,DMA,GPU 这些设备就是挂在计算机下面的。那么,操作系统,如何使应用程序能访问这些设备?
本质上需要驱动的原因:操作系统需要能够访问和操作这些设备。
我们知道,IO设备在计算机看来,或者说在处理器看来就是一组#寄存器和协议#
。
本节内容主要解决两个问题:
1、什么是设备的驱动程序
2、Linux设备抽象
设备驱动程序原理
IO设备的主要功能:输入和输出能够读写字节序列,流或者数组常见的设备都满足这个模型
终端/串口–字节流char_device 打印机–字节流,例如postscript文件 硬盘–字节数组,按照块访问 GPU–字节流(控制)+字节数组(显示存储器)
1 | 所以: |
把设备的寄存器直接暴露给用户是很糟糕和危险的,这显而易见。 这样,也给应用层的软件带来了很大的负担,出错的代价也会很大的 所以,我们要对设备做抽象,要在操作系统和实体设备(寄存器和协议)之间做一个抽象的层
这个尽可能统一的方式,如同一层API,就是设备驱动程序 我们不用知道寄存器的编号是多少,不用知道写进去后怎么样才能操作完成 这一层,就叫做驱动。
所有的这些设备:I/O设备,最重要的功能就是:数据往应用里送往外出。 char——device
补充一下字节流byte_stream,比如说,键盘的按键,它输入的就是一系列的事件,按下的这一大串按键 就可以看作一个字节流
block——device一块一块的,字节块。 有意思的事情:我们的显卡,是什么设备? 显存不是按块访问的,显卡暨是字节流,又是一个字节数组
驱动
这一大坨设备的抽象,最重要的就是读写和控制,设备驱动程序就是为设备建立起这个模型的代码
需要一段代码,需要把例如read这一段系统调用,翻译成设备寄存器能听得懂的这一段话。
这一段代码,把系统调用翻译,注意是翻译,我们能看到的一大坨通用API,变成一堆五花八门的设备之间的翻译
其实shell也是类似的原理,
shell是把命令,翻译成一组系统调用,这些系统调用的序列,再通过驱动层,翻译成为了实际的寄存器操作,被执行了起来,就是一层层往下的这个过程