跳到主要内容

Linux 设备驱动

什么是设备驱动

设备驱动是应用程序和硬件设备之间的一个软件层 。在 Linux 系统中,这个软件层一般是在内核中实现,通常以内核模块的形式存在。

设备驱动程序的作用在于提供机制,而不是提供策略,编写访问硬件的内核代码时不要给用户强加任何策略。

  • 机制:驱动程序能实现什么功能。
  • 策略:用户如何使用这些功能。

Linux 设备的分类及特点

计算机系统的硬件主要由 CPU、存储器和外设组成。随着 IC 制作工艺的发展,目前,芯片的集成度越来越高,往往在 CPU 内部就集成了存储器和外设控制器。比如,相当多的 ARM、PowerPC、MIPS 等处理器都集成了 UART、I2C 控制器、SPI 控制器、USB 控制器、SDRAM 控制器、以太网控制器等等,高端的处理器还集成了 GPU(图形处理器)、VPU(视频处理器)等。

我们所说的“驱动程序”针对的对象是存储器和外设(包括 CPU 内部集成的存储器和外设),而不是针对 CPU 内核。而在 Linux 系统中,则根据设备操作特点的不同,将设备分为三大类:字符设备、块设备、网络设备。

  • 字符设备 —— 是指必须以串行顺序依次进行访问的设备,即只能逐个字节进行读写操作,而不能随机读取设备中的某一数据。常见的字符设备有鼠标、键盘、触摸屏、串口、控制台、LED 等。
    • 块设备 —— 可以按任意顺序进行访问,以块为单位进行操作,如硬盘、eMMC 等。字符设备和块设备的驱动设计有很大差异,但每一个字符设备或块设备都在 /dev 目录下对应一个设备文件,对于用户而言,它们都可以使用 open()close()read()write() 等系统接口进行访问。
  • 网络设备 —— 面向网络数据包的接收和发送而设计的设备,并不对应于文件系统的设备节点。与字符设备或块设备的操作方式不同,网络设备主要使用套接字接口(socket)。

Linux 设备驱动与系统层次

除了网络设备外,字符设备与块设备都被映射到 Linux 文件系统的文件和目录,通过文件系统的系统调用接口(如 open()read()write()close() 等)即可访问字符设备和块设备。所有字符设备和块设备都统一呈现给用户。

Linux 的块设备有两种访问方法:

  • 一种是类似 dd 命令对应的原始块设备,如“/dev/sdb1”
  • 另一种是在块设备上建立 FAT、EXT4、BTRFS 等文件系统,然后以文件路径(如“/home/getiot/hello.txt”)的形式进行访问。

在 Linux 中,针对 NOR、NAND 等提供了独立的内存技术设备(Memory Technology Device,MTD)子系统,其上运行 YAFFS2、JFFS2、UBIFS 等具备擦除和负载均衡能力的文件系统。针对磁盘或者 Flash 设备的 FAT、EXT4、YAFFS2、JFFS2、UBIFS 等文件系统定义了文件和目录在存储介质上的组织。而 Linux 的虚拟文件系统则统一对它们进行了抽象。

应用程序可以使用 Linux 的系统调用接口编程,也可以使用 C 库函数,出于代码可移植性的目的,后者更值得推荐。实际上,C 库函数本身也是通过系统调用接口实现的,如 C 库函数 fopen()fwrite()fread()fclose() 分别会调用操作系统的接口 open()write()read()close()