Linux-----驱动

一、内核驱动与启动流程

1. Linux内核驱动
  • Nor Flash: 可线性访问,有专门的数据及地址总线(与内存访问方式相同)。

  • Nand Flash: 不可线性访问,访问需要控制逻辑(软件)。

2. Linux启动流程
  • ARM架构:

    • IRAM (4KB): 内部RAM,用于存储初始引导程序。

    • Nor Flash (2M): 存储u-boot程序。

    • 内存 (64M): 用于加载内核和根文件系统。

    • Nand Flash (256M): 存储内核、根文件系统等数据。

  • 启动过程:

    1. Bootloader (u-boot):

      • 初始化CPU、异常向量表、栈、时钟、内存等。

      • 关闭看门狗、中断、Cache、MMU。

      • 初始化相关硬件和软件协议。

      • 将内核加载到内存。

      • 向内核传递参数(根文件系统类型、位置、控制台等)。

      • 启动内核。

    2. 内核 (kernel):

      • 文件管理、内存管理、进程管理、网络管理、设备管理。

      • 启动到最后阶段加载根文件系统。

      • init进程启动后台服务程序、加载配置、启动shell和应用程序。

    3. 根文件系统 (rootfs):

      • 包含程序(应用、系统、命令)、配置文件、库文件、普通文件(txt、mp3)。
3. Windows与Linux对比
  • Windows: 使用BIOS启动。

  • Linux: 使用bootloader引导内核启动,内核加载rootfs。

4. 具体启动步骤
  • Nor Flash:

    • 系统上电后,PC指向0地址,直接执行Nor Flash中的u-boot程序。
  • Nand Flash:

    • 系统上电后,自动搬移u-boot前4KB程序到IRAM。

    • CPU执行IRAM中的代码,u-boot初始化内存并将剩余代码搬移到内存执行。

5. 内核与文件系统
  • 内核 (uImage):

    • 启动前u-boot向内核传递参数(tag_list)。

    • Nand Flash: u-boot直接读取Nand Flash中的uImage并写入内存的0x30008000地址处,启动内核。

    • Ubuntu: 通过TFTP下载uImage到内存的0x30008000地址处,启动内核。

  • 根文件系统 (rootfs):

    • Nand Flash: uImage启动到最后阶段时,直接挂载Nand Flash中的rootfs。

    • Ubuntu: uImage启动到最后阶段时,通过NFS挂载Ubuntu中的rootfs。

6. 前置步骤
  1. 向Nor Flash 0地址处烧写u-boot.bin。

  2. 拷贝uImage到Ubuntu的TFTP服务目录下。

  3. 将rootfs.tar.gz拷贝到Ubuntu的NFS服务目录下,并解压

    复制代码
    sudo tar -xvf rootfs.tar.gz
7. U-Boot命令
  • 环境变量管理:

    • printenv: 打印环境变量。

    • reset: 重启。

    • setenv serverip 192.168.1.3: 设置环境变量。

    • saveenv: 保存环境变量到Nand Flash。

    • setenv serverip: 删除环境变量。

  • 下载与启动:

    • tftp 0x30008000 uImage: 通过TFTP协议下载uImage到内存的0x30008000地址处。

    • bootm 0x30008000: 启动内存0x30008000地址处的内核。

    • go 0x30008000: 运行内存0x30008000地址处的程序。

8. 设置启动参数
复制代码
setenv bootargs console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.1.3:/home/linux/nfs/rootfs ip=192.168.1.123 init=/linuxrc
  • console: 控制台(终端)。

  • root: 根文件系统类型。

  • nfsroot: 根文件系统位置。

  • ip: 内核阶段使用的IP。

  • init: 指定init进程。

二、内核编译

1. 内核编译步骤
  • Kconfig : 定义make menuconfig的配置选项。

  • make menuconfig: 内核配置。

  • .config: 配置文件,决定哪些文件被编译进内核。

    • CONFIG_SSL = n: 不启用SSL。

    • CONFIG_MM = y: 启用内存管理。

  • makefile: 条件编译,编译内核。

2. 内核镜像类型
  • Image: 可以直接使用的内核镜像。

  • zImage: 一段解压代码 + Image的压缩文件。

  • uImage: 64字节的头信息 + zImage。

3. 地址相关代码
  • 地址相关代码: 链接地址和加载地址一致。

  • 地址无关代码: 链接地址和加载地址无关。

4. 跳转指令
  • 相对跳转、短跳转 : b fun

  • 绝对跳转、长跳转 : ldr pc, 0x00000000

5. 内核目录结构
6. 向内核新增文件

以向drivers/char下添加demo.c为例:

  1. drivers/char目录下新建并编辑demo.c

  2. 修改同层目录下的Makefile,添加:

    makefile

    复制代码
    obj-$(CONFIG_DEMO) += demo.o
  3. 修改同层目录下的Kconfig,添加一个DEMO的配置。

  4. 执行make menuconfig

  5. 执行make uImage

7. 内核编译命令
  • 配置内核

    复制代码
    cp config_mini2440_t35 .config
    make menuconfig
  • 编译内核

    复制代码
    make uImage
8. 内核镜像说明
  • Image: 可直接使用的内核镜像。

  • zImage: 压缩的内核镜像,包含解压代码。

  • uImage: 带有64字节头信息的压缩内核镜像。

9. Makefile和Kconfig
  • 每层目录都有MakefileKconfig文件,用于配置和编译内核。
10. 编译流程总结
  1. 配置内核 : 使用make menuconfig选择内核配置选项。

  2. 编译内核 : 使用make uImage生成内核镜像。

  3. 验证内核: 确保生成的内核镜像可以正常启动。

11. 注意事项
  • 配置文件 : .config文件决定了哪些模块被编译进内核。

  • 条件编译 : 使用obj-$(CONFIG_XXX)进行条件编译。

  • 目录结构 : 每层目录都有MakefileKconfig文件,确保编译过程正确。

三、驱动程序

1. 设备文件与驱动模块
  • 设备文件: 用户空间程序通过设备文件与驱动程序交互。

    • 示例: open("/dev/led");
  • 驱动模块: 内核中的驱动程序负责控制硬件设备。

    • 示例: sys_open(led)调用驱动模块。
2. 设备驱动类型
  • 字符设备驱动: 数据按顺序访问,90%以上的设备使用字符设备驱动。

  • 块设备驱动: 可以随机访问,主要用于存储设备。

  • 网络设备驱动: 网卡,集成复杂协议,通过套接字通信,没有设备号,靠名字维护。

3. 设备号
  • 设备号: 用于标识设备。

    • 主设备号 (高12位): 区分设备类型。

    • 次设备号 (低20位): 区分同类的不同设备。

  • 示例: dev_t 是32位设备号。

4. 创建设备节点
  • 使用mknod命令创建设备节点

    复制代码
    mknod /dev/demo3 c 255 0
    • /dev/demo3: 设备节点名。

    • c: 字符设备。

    • 255: 主设备号。

    • 0: 次设备号。

5. 驱动模块结构
  • 驱动模块 : 包含openreadwriteioctlclose等函数。

  • 示例: drv_leddrv_keydrv_adc分别对应LED、按键、ADC设备。

6. 设备驱动流程
  1. 应用程序调用设备文件:

    • open("/dev/led");
  2. 内核调用驱动模块:

    • sys_open(led)drv_led
  3. 驱动模块控制硬件设备:

    • drv_led控制LED设备。
7. 设备号与驱动模块关系
  • 每个设备号对应一个驱动模块。

  • 内核通过设备号找到对应的驱动模块。

8. 设备号结构
复制代码
+--------+--------+----+-------+
| 8      | 8      | 2  | 14    |
+--------+--------+----+-------+
设备类型  命令编号  数据  参数大小
魔幻数           流向
  • 设备类型 (魔幻数): 8位,标识设备类型。

  • 命令编号: 8位,标识具体命令。

  • 数据流向: 2位,标识数据方向。

  • 参数大小: 14位,标识参数大小。

9. 设备驱动总结
  • 字符设备: 顺序访问,适用于大多数设备。

  • 块设备: 随机访问,适用于存储设备。

  • 网络设备: 复杂协议,通过套接字通信。

  • 设备号: 区分设备类型和具体设备。

  • 驱动模块: 内核中的程序,负责控制硬件设备。

10. 关键命令
  • 创建设备节点 : mknod

  • 设备文件操作 : openreadwriteioctlclose

11. 注意事项
  • 设备号分配: 确保主设备号和次设备号唯一。

  • 驱动模块编写 : 需要实现openreadwrite等函数。

  • 设备文件操作: 应用程序通过设备文件与驱动模块交互。

相关推荐
两点王爷1 小时前
docker 运行自定义化的服务-后端
运维·docker·容器
邪恶的贝利亚2 小时前
FFMEPG常见命令查询
linux·运维·网络·ffmpeg
搜搜秀2 小时前
find指令中使用正则表达式
linux·运维·服务器·正则表达式·bash
弧襪3 小时前
Ubuntu vs CentOS:Shell 环境加载机制差异分析
linux·ubuntu·centos
七七powerful3 小时前
使用opentelemetry 可观测监控springboot应用的指标、链路实践,使用zipkin展示链路追踪数据,使用grafana展示指标
运维
Archie_IT4 小时前
修图自由!自建IOPaint服务器,手机平板随时随地远程调用在线P图
运维·服务器·前端·git·深度学习·npm·conda
行思理4 小时前
centos crontab 设置定时任务访问链接
linux·运维·centos
阳光明媚大男孩4 小时前
24.0.2 双系统ubuntu 安装显卡驱动黑屏,系统启动界面键盘失灵
linux·ubuntu·计算机外设
无名之逆4 小时前
[特殊字符] Hyperlane:为现代Web服务打造的高性能Rust文件上传解决方案
服务器·开发语言·前端·网络·后端·http·rust
再玩一会儿看代码5 小时前
[特殊字符] 深入理解 WSL2:在 Windows 上运行 Linux 的极致方案
linux·运维·windows·经验分享·笔记·学习方法