第三章:字符设备驱动-0:The Design of scull

The goal of this chapter is to write a complete char device driver. We develop a char acter driver because this class is suitable for most simple hardware devices. Char drivers are also easier to understand than block drivers or network drivers (which we get to in later chapters). Our ultimate aim is to write a modularized char driver, but we won’t talk about modularization issues in this chapter.

本章的目标是编写一个完整的字符设备驱动。我们选择开发字符驱动,是因为这类驱动适用于大多数简单硬件设备,且比块设备驱动或网络设备驱动(后续章节会介绍)更易理解。我们的最终目的是实现一个模块化的字符驱动,但本章暂不讨论模块化相关问题。

Throughout the chapter, we present code fragments extracted from a real device driver: scull (Simple Character Utility for Loading Localities). scull is a char driver that acts on a memory area as though it were a device. In this chapter, because of that peculiarity of scull, we use the word device interchangeably with “the memory area used by scull.”

在本章中,我们会展示从真实设备驱动 ——scull(Simple Character Utility for Loading Localities,即 “用于加载区域的简单字符工具”)中提取的代码片段。scull 是一款字符驱动,它会将一块内存区域当作设备来操作。正因为 scull 有这样的特性,本章中会将 “设备” 与 “scull 所使用的内存区域” 互换使用。
The advantage of scull is that it isn’t hardware dependent. scull just acts on some memory, allocated from the kernel. Anyone can compile and run scull, and scull is portable across the computer architectures on which Linux runs. On the other hand, the device doesn’t do anything “useful” other than demonstrate the interface between the kernel and char drivers and allow the user to run some tests.

scull 的优势在于它不依赖具体硬件。它仅对从内核中分配的一块内存进行操作,任何人都可以编译并运行 scull,且 scull 能在 Linux 支持的所有计算机架构上实现跨平台运行。但另一方面,这款 “设备” 除了演示内核与字符驱动之间的接口、允许用户进行一些测试外,并无其他 “实际用途”。

The Design of scull

The first step of driver writing is defining the capabilities (the mechanism) the driver will offer to user programs. Since our “device” is part of the computer’s memory, we’re free to do what we want with it. It can be a sequential or random-access device, one device or many, and so on.

驱动编写的第一步,是定义驱动将向用户程序提供的功能(即 “机制”)。由于我们的 “设备” 本质是计算机内存的一部分,因此可以灵活定义其功能 —— 它既可以是顺序访问设备或随机访问设备,也可以是单个设备或多个设备等。

To make scull useful as a template for writing real drivers for real devices, we’ll show you how to implement several device abstractions on top of the computer memory, each with a different personality.

The scull source implements the following devices. Each kind of device implemented by the module is referred to as a type.

为了让 scull 能作为 “真实设备驱动” 的编写模板,我们会展示如何在计算机内存之上实现多种设备抽象,每种抽象都具备不同的特性。

scull 源码实现了以下几类设备,模块实现的每类设备都被称为一种 “类型”。

scull0 to scull3

Four devices, each consisting of a memory area that is both global and persistent. Global means that if the device is opened multiple times, the data contained within the device is shared by all the file descriptors that opened it. Persistent means that if the device is closed and reopened, data isn’t lost. This device can be fun to work with, because it can be accessed and tested using conventional commands, such as cp, cat, and shell I/O redirection.

这类设备共 4 个,每个设备对应一块 “全局且持久” 的内存区域,具体特性如下:

  • 全局(Global):若设备被多次打开,所有打开该设备的文件描述符都会共享设备内的数据。

  • 持久(Persistent):即使设备被关闭后重新打开,数据也不会丢失。

这类设备使用起来很直观,因为可以通过 cpcat 以及 Shell I/O 重定向等常规命令对其进行访问和测试。

scullpipe0 to scullpipe3

Four FIFO (first-in-first-out) devices, which act like pipes. One process reads what another process writes. If multiple processes read the same device, they contend for data. The internals of scullpipe will show how blocking and non-blocking read and write can be implemented without having to resort to interrupts. Although real drivers synchronize with their devices using hardware
interrupts, the topic of blocking and nonblocking operations is an important one and is separate from interrupt handling (covered in Chapter 10).

这类设备共 4 个,是具备 FIFO(先进先出)特性的设备,行为类似管道(pipe):

  • 一个进程写入的数据,会被另一个进程读取。

  • 若多个进程读取同一个设备,它们会竞争获取数据。

scullpipe 的内部实现会展示 “如何在不依赖中断的情况下,实现阻塞式与非阻塞式的读写操作”。尽管真实驱动会通过硬件中断与设备同步,但 “阻塞 / 非阻塞操作” 本身是一个重要知识点,且与中断处理(第 10 章讲解)是相互独立的概念。

scullsingle、scullpriv、sculluid、scullwuid

These devices are similar to scull0 but with some limitations on when an open is permitted. The first (scullsingle) allows only one process at a time to use the driver, whereas scullpriv is private to each virtual console (or X terminal session), because processes on each console/terminal get different memory areas. sculluid and scullwuid can be opened multiple times, but only by one user at a time; the former returns an error of “Device Busy” if another user is locking the
device, whereas the latter implements blocking open. These variations of scull would appear to be confusing policy and mechanism, but they are worth looking at, because some real-life devices require this sort of management.

这四类设备与 scull0 类似(均基于内存区域),但在 “何时允许打开设备” 上存在限制,具体差异如下:

  • scullsingle:同一时间仅允许一个进程使用驱动(即排他性打开)。

  • scullpriv:每个虚拟控制台(或 X 终端会话)私有 —— 不同控制台 / 终端上的进程会获取独立的内存区域,数据互不干扰。

  • sculluid:允许多次打开,但同一时间仅允许一个用户操作;若其他用户正在锁定设备,新打开操作会返回 “设备忙”(Device Busy)错误。

  • scullwuid:与 sculluid 类似,但会通过 “阻塞式打开” 等待设备释放,而非直接返回错误。

Each of the scull devices demonstrates different features of a driver and presents different difficulties. This chapter covers the internals of scull0 to scull3; the more advanced devices are covered in Chapter 6. scullpipe is described in the section “A Blocking I/O Example,” and the others are described in “Access Control on a Device File.”

这些 scull 变体看似混淆了 “机制与策略”(前文提到的内核设计原则),但仍值得研究 —— 因为现实中部分设备(如独占式硬件)确实需要这类访问管理逻辑。

补充说明:

  1. “机制” 与 “策略” 的平衡

    ​​​​scull 的设计体现了驱动开发的核心思路:先确定 “机制”(如内存读写、FIFO 传输),再通过变体补充 “策略”(如访问权限、打开限制)。真实驱动中,“机制” 是驱动的核心功能(如与硬件的通信逻辑),“策略” 则是基于业务需求的附加规则(如并发控制),二者分离可让驱动更灵活、可复用。

  2. 不同设备类型的教学意义

    • scull0~scull3:覆盖字符驱动的基础接口(open/read/write/release),是入门核心;

    • scullpipe:聚焦 “阻塞 / 非阻塞 I/O”,解决用户态程序与驱动的同步问题,是进阶重点;

    • 其他变体:演示 “设备访问控制”,对应真实场景中的并发管理、权限隔离需求,是实战必备。

  3. 设备文件与设备的对应关系

    每类 scull 设备在 /dev 目录下会对应一个或多个设备文件(如 /dev/scull0/dev/scullpipe1)。用户态程序通过操作这些设备文件,间接调用 scull 驱动的接口 —— 这是 Linux 设备驱动的统一交互方式,所有设备均遵循此逻辑。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值