目录
1:前言
最近接触linux的比较多,因此想要系统性的把linux的整个实现框架给理清楚一点,以便后面来重新温故而知新。
本篇笔记是学习
2: 《linux-kernel - Linux 驱动架构简析 - 个人文章 - SegmentFault 思否》
2: linux模型分层
1:硬件层:最底层的硬件层负责与硬件设备进行交互,包括硬件的初始化、数据传输等操作。
2:总线/设备核心层:(1)主要用于总线管理设备和驱动的匹配。(2)(BUS,Device Core)触发驱动中的“probe()”函数在设备匹配的时候被调用。
3:设备模型/驱动子系统 :(1)包括字符设备、块设备、网络设备等驱动框架 。(2)驱动通过“cdev_add()”注册字符设备、关联操作函数。
4:虚拟文件系统(文件系统层):统一抽象文件操作(如"file_operations"结构体)
5:系统调用接口(Syscall):提供POSIX接口(如“open()”,“read()”)
6:应用层:用户程序通过系统调用操作设备。
3:各个层级之间的功能和交互关系
-
硬件层
-
物理硬件设备(如 GPIO、I2C 设备、磁盘控制器)。
-
提供底层硬件操作接口(如寄存器读写、中断响应)。
-
-
总线/设备核心层
-
设备管理:维护设备列表,处理设备注册/注销(如
device_register())。 -
驱动匹配:通过总线类型(如
platform_bus_type)匹配设备与驱动,触发probe()。 -
事件处理:处理设备插拔、电源状态变更(如 USB 热插拔)。
-
-
设备模型/驱动子系统
-
驱动实现:具体设备的操作(如字符设备
cdev、块设备gendisk)。 -
关联操作函数:实现
file_operations中的open()、read()、write()等函数。 -
设备抽象:将硬件设备抽象为内核对象(如
struct device),供上层统一管理。
-
-
虚拟文件系统 (VFS)
-
统一接口:抽象所有文件操作(设备、磁盘文件、网络套接字等)为
file_operations。 -
路径解析:将用户路径(如
/dev/ttyS0)映射到具体设备的操作函数。 -
挂载管理:支持多种文件系统(如 ext4、procfs、sysfs)。
-
-
系统调用接口 (Syscall)
-
用户-内核切换:将用户空间的 API(如
open())转换为内核函数(如sys_open())。 -
权限检查:验证用户程序是否有权访问设备或文件(如 SELinux 策略)。
-
-
应用层
-
用户程序:通过标准库(如 glibc)调用文件操作接口访问设备或文件。
-
设备抽象为文件:操作设备时使用与文件相同的接口(如
read()读取传感器数据)。
-
4:分层模型应用模型介绍
下面给出各个层级的分层流程示例。
(1)驱动层
// my_char_driver.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#define DEVICE_BUF_SIZE 1024
static char device_buffer[DEVICE_BUF_SIZE]; // 模拟硬件层
static int major_num;
static struct class *my_class;
static struct cdev my_cdev;
// 文件操作函数实现
static int my_open(struct inode *inode, struct file *file) {
printk("Device opened\n");
return 0;
}
static ssize_t my_read(struct file *file, char __user *buf, size_t len, loff_t *offset) {
copy_to_user(buf, device_buffer, len); // 从“硬件”读取数据到用户空间
return len;
}
static ssize_t my_write(struct file *file, const char __user *buf, size_t len, loff_t *offset) {
copy_from_user(device_buffer, buf, len); // 从用户空间写入“硬件”
return len;
}
static int my_release(struct inode *inode, struct file *file) {
printk("Device closed\n");
return 0;
}
static struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
.write = my_write,
.release = my_release,
};
// Platform 驱动与设备匹配
static int my_probe(struct platform_device *pdev) {
major_num = register_chrdev(0, "my_char_device", &my_fops);
if (major_num < 0) return major_num;
my_class = class_create(THIS_MODULE, "my_char_class");
if (IS_ERR(my_class)) {
unregister_chrdev(major_num, "my_char_device");
return PTR_ERR(my_class);
}
device_create(my_class, NULL, MKDEV(major_num, 0), NULL, "mydev");
return 0;
}
static int my_remove(struct platform_device *pdev) {
device_destroy(my_class, MKDEV(major_num, 0));
class_destroy(my_class);
unregister_chrdev(major_num, "my_char_device");
return 0;
}
static struct platform_driver my_platform_driver = {
.probe = my_probe,
.remove = my_remove,
.driver = {
.name = "my_char_device",
.owner = THIS_MODULE,
},
};
static struct platform_device my_platform_device = {
.name = "my_char_device",
.id = -1,
};
static int __init my_init(void) {
platform_device_register(&my_platform_device); // 注册 Platform 设备
platform_driver_register(&my_platform_driver); // 注册 Platform 驱动
return 0;
}
static void __exit my_exit(void) {
platform_driver_unregister(&my_platform_driver);
platform_device_unregister(&my_platform_device);
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
(2)应用层
// 用户态测试代码(test_app.c)
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
int fd = open("/dev/mydev", O_RDWR);
char buf[64] = "Hello from user!";
write(fd, buf, sizeof(buf)); // 写入驱动
read(fd, buf, sizeof(buf)); // 从驱动读取
close(fd);
return 0;
}
重点分析:
-
硬件层:通过
device_buffer模拟硬件存储。 -
总线/设备核心层:通过
platform_device和platform_driver实现设备与驱动的匹配。 -
设备模型/驱动子系统:通过
register_chrdev注册字符设备,绑定file_operations。 -
虚拟文件系统层 (VFS):将
/dev/mydev映射到驱动的my_read和my_write。 -
系统调用接口层:用户调用
open()、read()时触发内核的sys_open()、sys_read()。 -
应用层:用户程序通过文件接口操作设备。
而在这个系统调用接口层:
假设用户程序执行 open("/dev/mydev", O_RDWR):
-
用户空间 → 系统调用接口层
-
open()调用glibc库函数,触发软中断(如int 0x80或syscall指令)进入内核态。 -
内核执行
sys_open系统调用。
-
-
系统调用接口层 → 虚拟文件系统(VFS)
-
sys_open解析路径/dev/mydev,发现它是一个字符设备文件。 -
VFS 根据设备号(主设备号/次设备号)找到对应的
file_operations结构体(由驱动注册)。
-
-
虚拟文件系统 → 驱动层
-
VFS 调用
file_operations中的.open成员(即驱动实现的my_open函数)。 -
my_open执行驱动自定义的初始化操作(如配置硬件寄存器)。
-
-
驱动层 → 硬件层
-
驱动可能需要与硬件交互(如初始化设备寄存器、申请中断)。
-
小结:
系统调用接口层(如 sys_open)是内核的通用入口,不直接关联驱动。
驱动函数(如 my_open)通过 file_operations 注册到 VFS,由 VFS 在设备操作时调用。
流程链条:
用户 open() → 系统调用 sys_open → VFS 路径解析( file_operations) → 驱动 my_open。
5:总结
1. 分层模型概述
Linux 驱动架构采用分层设计,各层职责明确,协作完成用户程序与硬件设备的交互。以下是核心层级及其功能:
| 层级 | 核心功能 | 关键数据结构/函数 |
|---|---|---|
| 硬件层 | 物理硬件设备(如寄存器、内存、外设)及其底层操作接口(如寄存器读写、中断处理)。 | 无特定结构,依赖硬件手册定义。 |
| 总线/设备核心层 | 管理设备和驱动的匹配(如 Platform、PCI、USB 总线),触发驱动的 probe()/remove()。 | platform_device、platform_driver |
| 设备模型/驱动子系统 | 实现具体设备的操作(字符设备、块设备等),注册设备操作函数(file_operations)。 | cdev、file_operations |
| 虚拟文件系统(VFS) | 抽象所有文件操作(设备、磁盘文件、网络套接字等),提供统一的 file_operations 接口。 | inode、dentry、file |
| 系统调用接口层 | 用户空间与内核空间的桥梁,将 open()、read() 等转换为内核态系统调用(如 sys_open())。 | sys_open、sys_read |
| 应用层 | 用户程序通过标准库(如 glibc)调用文件接口操作设备或文件。 | open()、read()、write() |
2:各层级交互流程
以字符设备驱动为例,从驱动注册到用户访问的完整流程:
-
驱动初始化
-
总线/设备核心层:驱动通过
platform_driver_register()注册到总线(如Platform总线)。 -
设备模型/驱动子系统:在
probe()函数中注册字符设备(cdev_add()),绑定file_operations(如my_open、my_read)。 -
VFS:创建设备节点
/dev/mydev,关联设备号与file_operations。
-
-
用户访问设备
-
应用层:用户调用
open("/dev/mydev")。 -
系统调用接口层:触发
sys_open(),进入内核态。 -
VFS:解析路径,根据设备号找到对应的
file_operations,调用驱动实现的my_open()。 -
驱动层:通过
my_read()/my_write()与硬件层交互(如读写内存缓冲区)。
-



2059

被折叠的 条评论
为什么被折叠?



