文章目录
- 1 Linux 驱动开发架构图
- 2 更具体的例子:LED 驱动程序
- 2.1 硬件层(Hardware Layer)
- 2.2 固件层(Firmware Layer)
- 2.3 驱动程序层(Driver Layer)
- 2.4 操作系统内核(Kernel Layer)
- 2.5 系统调用层(System Call Layer)
- 2.6 C 库(C Library)
- 2.7 用户空间(User Space)
 
- 3 具体过程
- 4 从理解 `open()` 函数的层次到理解所有的架构层次
- 4.1 应用程序中的 `open()` 函数
- 4.2 C 库中的 `open()` 函数
- 4.3 `open()` 系统调用
- 4.4 驱动的 `open()` 函数
 
- 5 总结
- 参考链接
- 封面
- 本文将全面探讨 Linux 驱动开发在系统架构中的位置,包括应用程序、C 库、系统调用和内核之间的关系。
- Linux 驱动开发着眼于硬件和操作系统内核之间的驱动程序层,当然,内核配置与编译、引导加载程序开发、根文件系统构建等内容也是必不可少的。
1 Linux 驱动开发架构图
在 Linux 系统中,驱动开发涉及多个层级的交互,以下是各层级的结构图示:
2 更具体的例子:LED 驱动程序
以 LED 驱动程序为例,以下是各层级的具体作用:
2.1 硬件层(Hardware Layer)
- 组成:物理 LED 灯。
- 功能:发光和熄灭。
- 例子:LED 硬件连接到计算机的 GPIO(通用输入输出)引脚。
2.2 固件层(Firmware Layer)
- 组成:LED 控制芯片固件。
- 功能:管理 LED 的基本操作。
- 例子:初始化 LED 硬件并准备接收控制信号。
2.3 驱动程序层(Driver Layer)
- 组成:LED 驱动模块(如 led_driver.ko)。
- 功能: 
  - 硬件抽象:将 LED 的物理信号转换为标准输入/输出操作。
- 设备控制:处理 LED 的初始化和开/关控制。
- 文件操作:实现 open、close、read和write等函数。
 
- 例子:LED 驱动程序响应来自用户空间的 write操作,控制 LED 的开关状态。
2.4 操作系统内核(Kernel Layer)
- 组成:Linux 内核代码。
- 功能:管理系统资源,提供对硬件的低级访问。
- 例子:内核通过调用 LED 驱动程序中的函数来处理对 LED 的控制操作。
2.5 系统调用层(System Call Layer)
- 组成:如 open()、read()、write()系统调用。
- 功能:提供应用程序与内核交互的接口。
- 例子:当应用程序调用 write()系统调用时,系统调用层将请求传递给内核。
2.6 C 库(C Library)
- 组成:如 glibc 提供的标准库函数。
- 功能:实现对系统调用的包装,使其易于使用。
- 例子:open()、close()、read()和write()函数在 C 库中实现,最终调用系统调用。
2.7 用户空间(User Space)
- 组成:运行在操作系统上的应用程序,例如控制 LED 的程序。
- 功能:通过文件操作与设备驱动交互。
- 例子:控制 LED 的应用程序通过 open("/dev/led")打开设备文件,通过write()控制 LED 的开关状态。
3 具体过程
- LED 驱动开发:编写 LED 驱动代码 led_driver.c,实现 LED 初始化、开/关控制和文件操作函数。
- 编译驱动模块:将 led_driver.c编译为内核模块led_driver.ko。
- 加载模块:使用 insmod led_driver.ko加载驱动模块到内核中。
- 创建设备文件:在 /dev目录下创建led设备文件。
- 用户程序交互:应用程序使用 open("/dev/led")打开设备文件,通过write()控制 LED 的开关状态。
- 库函数调用:应用程序调用 C 库中的标准函数,如 open和write,这些函数通过系统调用与内核交互。
- 系统调用:C 库函数调用相应的系统调用,系统调用层将请求传递给内核。
- 驱动响应:LED 驱动处理来自系统调用的请求,控制 LED 的硬件操作。
4 从理解 open() 函数的层次到理解所有的架构层次
 
4.1 应用程序中的 open() 函数
 
- 功能:用于在应用程序中打开一个文件或者设备。
- 示例代码:
int fd = open("/dev/led", O_WRONLY);
4.2 C 库中的 open() 函数
 
- 功能:包装系统调用,提供一个易用的接口给用户空间程序。
- 伪代码:
int open(const char *pathname, int flags) {
    return syscall(SYS_open, pathname, flags);
}
4.3 open() 系统调用
 
- 功能:提供用户空间程序与内核交互的接口。
- 伪代码:
int sys_open(const char *filename, int flags) {
    // 内核代码,处理打开文件的逻辑
    ...
    return file_descriptor;
}
4.4 驱动的 open() 函数
 
- 功能:实现设备特定的打开操作逻辑。
- 示例代码:
static int led_open(struct inode *inode, struct file *file) {
    // 设备特定的打开操作,如初始化硬件
    ...
    return 0; // 成功
}
5 总结
- 通过本文的各个部分,可以清晰地看到 Linux 驱动开发在系统架构中的重要性。应用程序、C 库、系统调用和驱动程序之间的协作,使得用户能够方便地控制硬件设备,实现各种功能。
- Linux 驱动开发着眼于硬件和操作系统内核之间的驱动程序层,当然,内核配置与编译、引导加载程序开发、根文件系统构建等内容也是必不可少的。
参考链接
- Linux Device Drivers
- Linux Kernel Documentation
封面
由 DALL-E-3 生成
 ![![在这里插入图片描述][]](https://i-blog.csdnimg.cn/direct/55b528ce1f114c8e8e9eb684d3955111.png)


















