Linux驱动的分层模型学习笔记

目录

1:前言

2:linux模型分层

3:各个层级之间的功能和交互关系

硬件层

总线/设备核心层

设备模型/驱动子系统

虚拟文件系统 (VFS)

系统调用接口 (Syscall)

应用层

4:分层模型应用模型介绍

        (1):驱动层

        (2)应用层

重点分析:

5:总结

1. 分层模型概述

 2:各层级交互流程


1:前言

        最近接触linux的比较多,因此想要系统性的把linux的整个实现框架给理清楚一点,以便后面来重新温故而知新。

        本篇笔记是学习

        1:《深度解析: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:各个层级之间的功能和交互关系

  1. 硬件层

    • 物理硬件设备(如 GPIO、I2C 设备、磁盘控制器)。

    • 提供底层硬件操作接口(如寄存器读写、中断响应)。

  2. 总线/设备核心层

    • 设备管理:维护设备列表,处理设备注册/注销(如 device_register())。

    • 驱动匹配:通过总线类型(如 platform_bus_type)匹配设备与驱动,触发 probe()

    • 事件处理:处理设备插拔、电源状态变更(如 USB 热插拔)。

  3. 设备模型/驱动子系统

    • 驱动实现:具体设备的操作(如字符设备 cdev、块设备 gendisk)。

    • 关联操作函数:实现 file_operations 中的 open()read()write() 等函数。

    • 设备抽象:将硬件设备抽象为内核对象(如 struct device),供上层统一管理。

  4. 虚拟文件系统 (VFS)

    • 统一接口:抽象所有文件操作(设备、磁盘文件、网络套接字等)为 file_operations

    • 路径解析:将用户路径(如 /dev/ttyS0)映射到具体设备的操作函数。

    • 挂载管理:支持多种文件系统(如 ext4、procfs、sysfs)。

  5. 系统调用接口 (Syscall)

    • 用户-内核切换:将用户空间的 API(如 open())转换为内核函数(如 sys_open())。

    • 权限检查:验证用户程序是否有权访问设备或文件(如 SELinux 策略)。

  6. 应用层

    • 用户程序:通过标准库(如 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;
}

重点分析:

  1. 硬件层:通过 device_buffer 模拟硬件存储。

  2. 总线/设备核心层:通过 platform_device 和 platform_driver 实现设备与驱动的匹配。

  3. 设备模型/驱动子系统:通过 register_chrdev 注册字符设备,绑定 file_operations

  4. 虚拟文件系统层 (VFS):将 /dev/mydev 映射到驱动的 my_read 和 my_write

  5. 系统调用接口层:用户调用 open()read() 时触发内核的 sys_open()sys_read()

  6. 应用层:用户程序通过文件接口操作设备。

而在这个系统调用接口层:

假设用户程序执行 open("/dev/mydev", O_RDWR)

  1. 用户空间 → 系统调用接口层

    • open() 调用 glibc 库函数,触发软中断(如 int 0x80 或 syscall 指令)进入内核态。

    • 内核执行 sys_open 系统调用。

  2. 系统调用接口层 → 虚拟文件系统(VFS)

    • sys_open 解析路径 /dev/mydev,发现它是一个字符设备文件。

    • VFS 根据设备号(主设备号/次设备号)找到对应的 file_operations 结构体(由驱动注册)。

  3. 虚拟文件系统 → 驱动层

    • VFS 调用 file_operations 中的 .open 成员(即驱动实现的 my_open 函数)。

    • my_open 执行驱动自定义的初始化操作(如配置硬件寄存器)。

  4. 驱动层 → 硬件层

    • 驱动可能需要与硬件交互(如初始化设备寄存器、申请中断)。

小结:

系统调用接口层(如 sys_open)是内核的通用入口,不直接关联驱动

驱动函数(如 my_open)通过 file_operations 注册到 VFS,由 VFS 在设备操作时调用。

流程链条
用户 open() → 系统调用 sys_open → VFS 路径解析( file_operations) → 驱动 my_open

5:总结

1. 分层模型概述

Linux 驱动架构采用分层设计,各层职责明确,协作完成用户程序与硬件设备的交互。以下是核心层级及其功能:

层级核心功能关键数据结构/函数
硬件层物理硬件设备(如寄存器、内存、外设)及其底层操作接口(如寄存器读写、中断处理)。无特定结构,依赖硬件手册定义。
总线/设备核心层管理设备和驱动的匹配(如 PlatformPCIUSB 总线),触发驱动的 probe()/remove()platform_deviceplatform_driver
设备模型/驱动子系统实现具体设备的操作(字符设备、块设备等),注册设备操作函数(file_operations)。cdevfile_operations
虚拟文件系统(VFS)抽象所有文件操作(设备、磁盘文件、网络套接字等),提供统一的 file_operations 接口。inodedentryfile
系统调用接口层用户空间与内核空间的桥梁,将 open()read() 等转换为内核态系统调用(如 sys_open())。sys_opensys_read
应用层用户程序通过标准库(如 glibc)调用文件接口操作设备或文件。open()read()write()

 2:各层级交互流程

以字符设备驱动为例,从驱动注册到用户访问的完整流程:

  1. 驱动初始化

    • 总线/设备核心层:驱动通过 platform_driver_register() 注册到总线(如 Platform 总线)。

    • 设备模型/驱动子系统:在 probe() 函数中注册字符设备(cdev_add()),绑定 file_operations(如 my_openmy_read)。

    • VFS:创建设备节点 /dev/mydev,关联设备号与 file_operations

  2. 用户访问设备

    • 应用层:用户调用 open("/dev/mydev")

    • 系统调用接口层:触发 sys_open(),进入内核态。

    • VFS:解析路径,根据设备号找到对应的 file_operations,调用驱动实现的 my_open()

    • 驱动层:通过 my_read()/my_write() 与硬件层交互(如读写内存缓冲区)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值