学习计划

寒假两个月学习规划(Linux驱动方向)

目标:研二秋季投递大厂实习前,达到面经中Linux驱动/BSP方向除手撕代码外的面试水平

周期:8周(约2个月)


一、现状与差距分析

已有基础

模块 掌握程度 说明
STM32 扎实 GPIO/UART/I2C/DMA/定时器/中断/时钟,寄存器级理解
FreeRTOS 扎实 任务切换/PendSV/双栈/内存管理/调度机制
xv6 扎实 5个lab完成,页表/trap/COW fork,OS内功好
IMX6ULL 中等 U-Boot/LCD/I2C/SPI/RTC驱动,还没进入Linux驱动框架
RK3399项目 实战级 TypeC OTG切换/MIPI转LVDS屏幕适配,两年工业经验

面经考点差距表

模块 面经出现频率 当前状态 需要补的内容
C语言基础 几乎每场 有实战基础 static/volatile/const细节、内存对齐、指针高级用法
C++11 ~60% 薄弱 move/lambda/智能指针/STL容器
Linux驱动框架 核心必考 刚到U-Boot 字符设备→platform→设备树→子系统驱动
内核内存管理 ~70% xv6有底子 kmalloc/vmalloc/slab/buddy/mmap
进程与调度 ~60% xv6有底子 CFS、task_struct、IPC
同步机制 ~50% FreeRTOS有概念 mutex/spinlock/信号量/RCU
U-Boot ~40% 已学过 补bootcmd/bootargs/启动流程细节
ARM体系结构 ~40% 有基础 异常等级、MMU、Cache一致性
网络TCP/IP ~35% 薄弱 三次握手/四次挥手、socket、select/poll/epoll
调试工具 ~30% 一般 GDB、ftrace、coredump分析
Makefile/Shell ~25% 一般 Makefile语法、Shell脚本基础

二、8周详细规划

第1-2周:Linux驱动入门 + C语言查漏

Linux驱动(每天主力时间)

  • 字符设备驱动开发
    • file_operations 结构体
    • cdev、register_chrdev、alloc_chrdev_region
    • 设备号(主设备号/次设备号)
    • class_create / device_create 自动创建设备节点
  • 动手写一个LED字符设备驱动,从用户空间 open/write/ioctl 控制
  • 设备树基础
    • 设备树语法(DTS/DTB/DTC)
    • 节点、属性、compatible 字段
    • 设备树和驱动的匹配机制(of_match_table)
    • of_ 系列API:of_find_node_by_path、of_property_read_u32 等

C语言查漏(每天1小时)

  • static 的三种用法
    • 修饰局部变量:生命周期延长到程序结束
    • 修饰全局变量:限制作用域到本文件
    • 修饰函数:限制函数可见性到本文件
  • volatile 的作用和使用场景
    • 防止编译器优化,每次从内存读取
    • 场景:硬件寄存器、中断服务程序中的共享变量、多线程共享变量
  • const 与 #define 的区别
    • 类型检查、作用域、调试可见性
  • 指针专题
    • 指针与数组的区别
    • 函数指针、回调函数
    • 指针的指针(二级指针)
    • void* 的使用
  • 结构体内存对齐
    • 对齐规则、#pragma pack
    • sizeof 计算
  • 大小端(Big-endian / Little-endian)
    • 判断方法、转换函数
  • malloc 的实现原理
    • brk / mmap 系统调用
    • 内存碎片问题

第3-4周:platform驱动 + 设备树深入 + 内核内存管理

Linux驱动

  • platform总线驱动模型(面经必考)
    • platform_device 和 platform_driver
    • probe 和 remove 函数
    • 资源获取:platform_get_resource
  • 设备树与驱动的完整流程
    • pinctrl子系统:引脚复用配置
    • gpio子系统:of_get_named_gpio、gpio_request、gpio_direction_output
  • I2C子系统驱动(重点学框架,裸机协议你已经会了)
    • I2C核心层 / 适配器层 / 设备驱动层
    • i2c_driver、i2c_client
    • i2c_transfer / i2c_smbus_read_byte_data
  • SPI子系统驱动
    • spi_driver、spi_device
    • spi_sync / spi_async

内核内存管理

  • 物理内存管理
    • buddy system(伙伴系统):页的分配与合并
    • alloc_pages / free_pages
  • slab分配器
    • 解决buddy system小内存分配效率问题
    • kmem_cache_create / kmem_cache_alloc
  • kmalloc vs vmalloc vs kmap
    • kmalloc:物理连续,基于slab,用于小内存
    • vmalloc:虚拟连续物理不一定连续,用于大内存
    • kmap:映射高端内存
  • mmap 原理
    • 用户空间与内核空间的内存映射
    • remap_pfn_range
  • copy_from_user / copy_to_user
    • 为什么不能直接用 memcpy
    • 页错误处理
  • 用户空间虚拟内存布局
    • 代码段 / 数据段 / BSS / 堆 / 栈 / mmap区域
    • 4GB虚拟地址空间划分(3G用户 + 1G内核)

第5-6周:进程调度 + 同步机制 + C++11

内核进程与调度

  • task_struct 结构体关键字段
    • 进程状态(TASK_RUNNING / TASK_INTERRUPTIBLE / TASK_UNINTERRUPTIBLE)
    • PID、优先级、调度策略
    • mm_struct(内存描述符)
  • 进程状态转换
    • 创建→就绪→运行→阻塞→终止
    • 僵尸进程、孤儿进程
  • CFS调度器原理
    • 虚拟运行时间 vruntime
    • 红黑树组织就绪队列
    • 权重与nice值的关系
    • SCHED_NORMAL / SCHED_FIFO / SCHED_RR 的区别
  • 进程间通信(IPC)
    • 管道(pipe)和命名管道(FIFO)
    • 共享内存(效率最高)
    • 信号量(semaphore)
    • 消息队列
    • 信号(signal)
    • socket(可跨主机)
  • 中断上下半部
    • 上半部:硬中断,快速执行
    • 下半部:softirq / tasklet / workqueue
    • threaded irq
    • 各自适用场景

同步机制

  • 自旋锁(spinlock)
    • 忙等待,适用于中断上下文和短临界区
    • spin_lock / spin_lock_irqsave
  • 互斥锁(mutex)
    • 可睡眠,只能用于进程上下文
    • 适用于长临界区
  • 自旋锁 vs 互斥锁的选择(面经高频题)
    • 中断上下文 → 必须用自旋锁
    • 临界区很短 → 自旋锁
    • 临界区可能睡眠 → 互斥锁
  • 信号量 vs completion
  • 原子操作:atomic_t、atomic_read、atomic_set、atomic_inc
  • RCU基本概念
    • 读不加锁,写端等待所有读完成后再释放旧数据
    • 适用于读多写少场景
  • 死锁
    • 四个必要条件
    • 避免方法:固定加锁顺序、超时机制

C++11(每天1-1.5小时)

不需要精通,但面经中出现率约60%,需要能答上来

  • 基础特性
    • auto 类型推导
    • nullptr 替代 NULL
    • 范围for循环
    • enum class
  • 右值引用和移动语义
    • 左值 vs 右值
    • std::move 的作用:将左值转为右值引用,触发移动构造
    • 移动构造函数 vs 拷贝构造函数
    • std::forward 完美转发
  • 智能指针
    • std::shared_ptr:引用计数,共享所有权
    • std::unique_ptr:独占所有权,不可拷贝
    • std::weak_ptr:解决 shared_ptr 循环引用
  • lambda 表达式
    • 语法:[capture](params) -> return_type { body }
    • 捕获方式:[=] 值捕获、[&] 引用捕获
  • STL容器
    • vector:reserve vs resize、push_back vs emplace_back
    • map vs unordered_map(红黑树 vs 哈希表)
    • vector vs array

第7周:网络 + ARM体系结构 + 调试工具

网络基础

  • TCP三次握手(面经高频)
    • SYN → SYN+ACK → ACK
    • 为什么是三次不是两次
  • TCP四次挥手
    • FIN → ACK → FIN → ACK
    • TIME_WAIT状态的意义
  • TCP vs UDP
    • 可靠性、连接、顺序、效率
  • socket编程基本流程
    • 服务端:socket → bind → listen → accept → read/write → close
    • 客户端:socket → connect → read/write → close
  • I/O多路复用(面经高频)
    • select:fd数量有限(1024),每次需要拷贝fd集合
    • poll:无fd数量限制,但仍需遍历
    • epoll:事件驱动,效率最高,epoll_create/epoll_ctl/epoll_wait
  • 其他协议
    • ARP协议:IP地址→MAC地址
    • DNS解析过程
    • ICMP:ping的原理

ARM体系结构补充

  • ARM异常等级
    • EL0(用户态)→ EL1(内核态)→ EL2(Hypervisor)→ EL3(Secure Monitor)
  • MMU工作原理
    • 页表(多级页表)、TLB(Translation Lookaside Buffer)
    • TLB miss的处理流程
    • 与xv6的页表机制对照理解
  • Cache
    • L1/L2/L3层级
    • Cache一致性问题(多核场景)
    • DMA操作时的Cache刷新
  • ARM启动流程
    • BootROM → BL1 → BL2 → BL31(TF-A) → U-Boot → Kernel
    • 对照你学过的U-Boot部分衔接理解

调试工具

  • GDB
    • 常用命令:break/next/step/print/backtrace/watch
    • 远程调试:gdbserver
  • 内核调试
    • printk 日志等级
    • 动态调试(dynamic debug)
    • ftrace:函数跟踪、事件跟踪
  • coredump分析
    • 生成coredump文件
    • 用GDB加载分析
  • dmesg 查看内核日志

第8周:Makefile/Shell + 面经实战 + 项目整理

Makefile/Shell/工具

  • Makefile
    • 基本语法:目标、依赖、命令
    • 自动变量:$@、$<、$^
    • 模式规则、伪目标
    • 内核模块的Makefile写法
  • Shell脚本基础
    • 变量、条件判断、循环
    • 常用命令:grep/sed/awk/find/xargs
  • Git
    • 分支管理、merge vs rebase
    • 解决冲突

面经实战

  • 逐条过面经PDF,针对Linux驱动/BSP相关的面试记录:
    • 重点场次:03、04、07、13、14、15、31、32、33、34、38号
    • 能答的打勾,不能答的记录下来回头补
  • 模拟面试练习
    • 找同学互相模拟,或者对着镜子讲
    • 每个知识点要能用自己的话讲2-3分钟

项目整理(面试竞争力核心)

  • RK3399 TypeC OTG项目 — STAR描述
    • S:什么产品、什么需求
    • T:你负责什么
    • A:具体怎么做的(改了哪些代码、遇到什么坑)
    • R:结果如何
  • RK3399 MIPI转LVDS屏幕适配项目 — STAR描述
    • 同上,重点准备:时序参数调试、DTS配置、调试过程
  • 准备好能讲15分钟的项目深度版本
  • 准备好3分钟的项目精简版本

三、每日时间分配

时间段 内容 说明
上午(3-4h) Linux驱动学习 + 实操 IMX6ULL跟着做,代码必须跑起来
下午前半(2h) 当周理论模块 内核原理 / C++ / 网络,按周计划推进
下午后半(1.5h) 写笔记 + 对照面经验证 学完一个点就去面经里找相关题
晚上(1-1.5h) C语言 / 回顾当天内容 查漏补缺

四、优先级说明

如果时间不够用,按以下顺序砍:

  1. 绝不能砍:Linux驱动框架(字符设备/platform/设备树/I2C子系统)、内核内存管理、同步机制
  2. 尽量保住:C语言细节、进程调度CFS、中断上下半部、C++11基础
  3. 可以精简:网络只需掌握TCP三握四挥 + epoll、ARM只需MMU + 启动流程
  4. 实在没时间可以考前突击:Makefile/Shell、调试工具细节

五、关于心态

  • 面经PDF里47场面试覆盖了BSP/RTOS/AI芯片/蓝牙/汽车电子等完全不同的方向,你只需要关注Linux驱动/BSP相关的15-20场
  • 深度比广度重要:能把Linux I2C子系统从用户空间到硬件寄存器完整讲清楚,比什么都知道一点但讲不深强得多
  • 你的RK3399项目经验是真正的差异化竞争力,很多应届生没有这个
  • 每周末回顾一次本周学了什么,对照面经检验,保持节奏感