八股文是一种特殊文体,每篇文章包括破题、承题、起讲、入手、起股、中股、后股、束股八个部分,要求严格对仗,字数有限定,题目出自《四书》。 而现在大家常用八股文来指代面试中常见的一些知识、问题。 日常工作中我们往往围绕业务逻辑进行开发而忽略这些看似简单却可能不能立马给出精确回答的八股问题上。 所以如果你有找工作/换工作的计划,请拿出点时间看看八股,唤醒一下记忆深处的那段代码。
1. platform 框架的原理是什么?驱动匹配流程?
platform 框架原理:Linux 内核提供的一种虚拟总线机制,把没有实际物理总线的设备(如 SoC 内部外设)纳入统一的设备模型管理。
驱动匹配流程:
设备注册:通过设备树或代码注册 platform_device
驱动注册:platform_driver_register() 注册驱动
匹配:内核遍历总线上的设备和驱动,按优先级尝试匹配:
① 设备树 compatible 属性与驱动 of_match_table 匹配
② id_table 名字匹配
③ platform_driver.driver.name 与 platform_device.name 匹配
匹配成功后调用驱动的 probe() 函数,驱动在其中获取资源、初始化硬件
设备和驱动谁先注册都行,内核会在另一方注册时自动触发匹配。
2. probe 函数通常完成什么工作?
probe 函数是驱动的入口初始化函数,匹配成功后由内核自动调用,通常完成以下工作:
- 解析设备信息:从设备树或
platform_data获取寄存器地址、中断号、时钟等资源 - 申请资源:
ioremap映射寄存器、request_irq注册中断、clk_get获取时钟 - 注册设备节点:向子系统注册(如
cdev、input_device、v4l2_device等),让用户态能访问 - 分配私有数据结构:用
devm_kzalloc 分配驱动私有数据并关联到device
3. 主设备号与次设备号的作用,怎么申请?
- 如
/dev/ttyS0(次设备号0)和 /dev/ttyS1(次设备号1)
MKDEV(major, minor):将主设备号和次设备号组合成完整的设备号(dev_t)- 提取设备号:
MAJOR(dev) / MINOR(dev) - 静态:
register_chrdev_region(dev, count, name) - 动态(推荐):
alloc_chrdev_region(&dev, 0, count, name)
4. 用户空间和内核空间的通信方式有哪些?
- 系统调用:最基本的方式(
open/read/write/ioctl) - procfs:
/proc/ 下创建文件,用户cat/echo操作 - netlink socket:异步双向通信,支持多播
- copy_to_user/copy_from_user:
read/write中的数据传递 - 字符设备:
ioctl/unlocked_ioctl
5. Linux驱动中有哪些内存分配函数?
- kmalloc:物理连续,基于
slab,快速,适合小块(<128KB) - kzalloc:=
kmalloc + memset(0),分配并清零 - vmalloc:虚拟连续但物理可能不连续,适合大块,开销大
- devm_kmalloc:设备管理版,设备移除时自动释放
小内存用kmalloc,大内存用vmalloc,驱动中优先devm_版本。
6. container_of(ptr, type, member)宏的作用和原理
作用:从成员指针反推出包含它的结构体指针。
定义:container_of(ptr, type, member)
原理:
(type *)((char *)ptr - offsetof(type, member))
- 用成员地址 减去 成员在结构体中的偏移量,得到结构体首地址
- 从
file->private_data 获取设备结构体
7. 编译器的优化等级-O0、-O1、-O2、-O3有什么区别?优化可能导致什么问题?
-O0:不优化,调试方便但运行慢。
-O1:基本优化。
-O2:推荐优化级别,平衡性能和编译速度。
-O3:激进优化(循环展开、向量化等)。
优化可能导致的问题:
- volatile遗漏暴露:不加
volatile的硬件寄存器访问被优化掉 - 时序变化:优化后代码执行速度变化,可能影响精确延时
8. 孤儿进程、僵尸进程、守护进程分别是什么?
- 孤儿进程:父进程先于子进程退出,子进程变成孤儿,被
init(PID=1)进程收养,由 init 负责回收。无害 - 僵尸进程:子进程退出后,父进程没有调用
wait()/waitpid() 回收其退出状态。子进程的 task_struct 还残留在内核中,状态为 Z(Zombie)。有害(占用 PID 和内核资源) - 守护进程(Daemon):在后台运行的服务进程,与终端脱离关联。如
sshd、crond。通常通过两次 fork() + setsid() 创建
9. Linux中的softirq、tasklet、workqueue的区别
三种下半部机制的核心区别:
- softirq:静态定义,可多CPU并行执行,性能最高,内核内部用(网络/块设备)
- tasklet:基于
softirq,同一tasklet不会多CPU并行,不能睡眠 - workqueue:基于内核线程,可以睡眠,可延时执行
选择原则:
10. Linux内核模块的加载和卸载过程
内核模块的加载和卸载过程:
加载(insmod/modprobe):
卸载(rmmod):
modprobe比insmod多了自动处理依赖关系的能力。