第7课 嵌入式Linux内核架构解析 模块二:内核核心机制
文章目录
- 第7课 嵌入式Linux内核架构解析 模块二:内核核心机制
- 一、课程目标
- 二、Linux内核核心定位
- 三、内核核心机制详解(含原理说明+样例代码)
- 1. 内核核心机制:进程与线程管理
- 1.1 基本概念
- 1.2 进程状态
- 1.3 示例代码(内核模块:查看进程信息)
- 2. 内核核心机制:进程调度
- 2.1 调度功能
- 2.2 常见调度策略
- 2.3 调度核心指标
- 2.4 示例代码(查看进程调度类)
- 3. 内核核心机制:内存管理
- 3.1 物理内存与虚拟内存
- 3.2 内存分配机制
- 3.3 内核空间与用户空间
- 3.4 示例代码(内核内存分配)
- 4. 内核核心机制:中断与异常处理
- 4.1 中断作用
- 4.2 中断处理流程
- 4.3 下半部机制(bottom half)
- 4.4 示例:嵌入式GPIO中断流程
- 4.5 示例代码(tasklet 下半部)
- 5. 内核核心机制:系统调用
- 5.1 基本概念
- 5.2 典型系统调用
- 5.3 示例代码(系统调用演示)
- 6. 内核核心机制:同步与互斥
- 6.1 作用
- 6.2 使用原则
- 6.3 示例代码(自旋锁)
- 7. 内核核心机制:定时器与延时机制
- 7.1 内核定时器
- 7.2 延时函数
- 7.3 示例代码(内核定时器)
- 8. 内核核心机制:工作队列与内核线程
- 8.1 基本概念
- 8.2 示例代码(工作队列)
- 四、课堂练习
- 五、课后作业
- 六、本章总结
- 七、核心关键词
- 回顾总结
- 上一节课作业答案: 嵌入式C语言进阶(适配实战)模块一:基础入门
- 代码功能说明
- 注意事项
一、课程目标
理解嵌入式Linux内核的核心定位与运行机制
掌握进程管理、调度、内存管理、中断管理、系统调用五大核心机制
理解内核空间与用户空间的隔离原理
掌握内核同步、锁机制、定时器、工作队列基础原理
为后续内核裁剪、驱动开发打下理论基础
二、Linux内核核心定位
Linux内核是硬件与应用层之间的核心中间层,负责统一管理硬件资源、调度任务、分配内存、处理中断,并为应用程序提供稳定接口。
嵌入式Linux内核特点:体积小、可裁剪、实时性可控、支持多种CPU架构(ARM、MIPS、RISC-V)。
三、内核核心机制详解(含原理说明+样例代码)
1. 内核核心机制:进程与线程管理
1.1 基本概念
进程:程序运行的实体,拥有独立内存空间
线程:轻量级进程,共享进程资源
PCB(进程控制块):内核管理进程的核心数据结构
1.2 进程状态
运行态、就绪态、阻塞态、终止态
嵌入式中常见:中断唤醒阻塞进程
1.3 示例代码(内核模块:查看进程信息)
#include <linux/module.h> #include <linux/sched.h> #include <linux/init.h> static int __init process_demo_init(void) { printk("当前进程 PID: %d\n", current->pid); printk("进程名称: %s\n", current->comm); printk("进程状态: %d\n", current->state); return 0; } static void __exit process_demo_exit(void) { printk("进程模块卸载\n"); } module_init(process_demo_init); module_exit(process_demo_exit); MODULE_LICENSE("GPL");2. 内核核心机制:进程调度
2.1 调度功能
决定哪个进程使用CPU,是嵌入式系统实时性的关键。
2.2 常见调度策略
CFS调度:普通进程,公平调度
RT调度:实时进程,高优先级优先
嵌入式常用:PREEMPT_RT补丁提升实时性
2.3 调度核心指标
响应时间、切换开销、优先级、抢占性
2.4 示例代码(查看进程调度类)
#include <linux/module.h> #include <linux/sched.h> static int __init sched_demo_init(void) { printk("当前进程调度类: %s\n", current->sched_class == &fair_sched_class ? "CFS 公平调度" : current->sched_class == &rt_sched_class ? "RT 实时调度" : "其他"); return 0; } static void __exit sched_demo_exit(void) { printk("调度模块卸载\n"); } module_init(sched_demo_init); module_exit(sched_demo_exit); MODULE_LICENSE("GPL");3. 内核核心机制:内存管理
3.1 物理内存与虚拟内存
内核负责将虚拟地址映射为物理地址
嵌入式系统通常开启MMU,实现地址隔离与保护
3.2 内存分配机制
伙伴系统:管理物理页框
SLAB/SLOB/Slub:小内存分配器(嵌入式常用SLOB)
3.3 内核空间与用户空间
0~3G:用户空间
3G~4G:内核空间(ARM 32位)
应用程序不能直接访问内核,必须通过系统调用
3.4 示例代码(内核内存分配)
#include <linux/module.h> #include <linux/slab.h> static int __init mem_demo_init(void) { void *buf; buf = kmalloc(1024, GFP_KERNEL); if (!buf) { printk("内存分配失败\n"); return -ENOMEM; } printk("内核内存分配成功: %p\n", buf); kfree(buf); return 0; } static void __exit mem_demo_exit(void) { printk("内存模块卸载\n"); } module_init(mem_demo_init); module_exit(mem_demo_exit); MODULE_LICENSE("GPL");4. 内核核心机制:中断与异常处理
4.1 中断作用
硬件向CPU发送信号,触发内核处理(如键盘、网卡、GPIO)
4.2 中断处理流程
中断发生 → 保存现场 → 执行中断服务程序 → 恢复现场
4.3 下半部机制(bottom half)
软中断、tasklet、工作队列
目的:缩短中断关闭时间,提升系统实时性
4.4 示例:嵌入式GPIO中断流程
按键按下 → GPIO中断触发 → 驱动中断处理 → 唤醒应用进程
4.5 示例代码(tasklet 下半部)
#include <linux/module.h> #include <linux/interrupt.h> void tasklet_func(unsigned long data) { printk("tasklet 下半部执行: %lu\n", data); } DECLARE_TASKLET(my_tasklet, tasklet_func, 666); static int __init irq_demo_init(void) { tasklet_schedule(&my_tasklet); printk("tasklet 调度成功\n"); return 0; } static void __exit irq_demo_exit(void) { tasklet_kill(&my_tasklet); printk("中断模块卸载\n"); } module_init(irq_demo_init); module_exit(irq_demo_exit); MODULE_LICENSE("GPL");5. 内核核心机制:系统调用
5.1 基本概念
系统调用是用户程序进入内核的唯一合法入口。
应用程序通过软中断(ARM为svc)进入内核态,执行内核函数后返回用户态。
5.2 典型系统调用
open、read、write、ioctl、fork、mmap
5.3 示例代码(系统调用演示)
#include <linux/module.h> #include <linux/syscalls.h> static int __init syscall_demo_init(void) { printk("系统调用号: %lu\n", __NR_getpid); printk("用户程序通过系统调用进入内核\n"); return 0; } static void __exit syscall_demo_exit(void) { printk("系统调用模块卸载\n"); } module_init(syscall_demo_init); module_exit(syscall_demo_exit); MODULE_LICENSE("GPL");6. 内核核心机制:同步与互斥
6.1 作用
嵌入式多任务并发必须保证资源安全,内核提供:
自旋锁 spinlock
互斥锁 mutex
信号量 semaphore
完成量 completion
6.2 使用原则
中断上下文用自旋锁,进程上下文可用互斥锁。
6.3 示例代码(自旋锁)
#include <linux/module.h> #include <linux/spinlock.h> static spinlock_t my_lock; static int __init sync_demo_init(void) { unsigned long flags; spin_lock_init(&my_lock); spin_lock_irqsave(&my_lock, flags); printk("自旋锁加锁成功\n"); spin_unlock_irqrestore(&my_lock, flags); return 0; } static void __exit sync_demo_exit(void) { printk("同步模块卸载\n"); } module_init(sync_demo_init); module_exit(sync_demo_exit); MODULE_LICENSE("GPL");7. 内核核心机制:定时器与延时机制
7.1 内核定时器
基于硬件时钟中断
用于周期性任务、超时处理
7.2 延时函数
udelay、mdelay、msleep
原子上下文不能用睡眠函数
7.3 示例代码(内核定时器)
#include <linux/module.h> #include <linux/timer.h> static struct timer_list my_timer; void timer_func(struct timer_list *timer) { printk("定时器超时执行\n"); } static int __init timer_demo_init(void) { my_timer.expires = jiffies + HZ * 2; my_timer.function = timer_func; add_timer(&my_timer); printk("定时器启动成功\n"); return 0; } static void __exit timer_demo_exit(void) { del_timer_sync(&my_timer); printk("定时器模块卸载\n"); } module_init(timer_demo_init); module_exit(timer_demo_exit); MODULE_LICENSE("GPL");8. 内核核心机制:工作队列与内核线程
8.1 基本概念
工作队列:把任务推后执行,运行在进程上下文,可睡眠。
内核线程:由内核创建,只在内核态运行,用于后台处理。
8.2 示例代码(工作队列)
#include <linux/module.h> #include <linux/workqueue.h> static struct work_struct my_work; void work_func(struct work_struct *work) { printk("工作队列执行\n"); } static int __init workq_demo_init(void) { INIT_WORK(&my_work, work_func); schedule_work(&my_work); printk("工作队列调度成功\n"); return 0; } static void __exit workq_demo_exit(void) { flush_work(&my_work); printk("工作队列模块卸载\n"); } module_init(workq_demo_init); module_exit(workq_demo_exit); MODULE_LICENSE("GPL");四、课堂练习
简述用户空间与内核空间的区别。
中断处理为什么要分上半部和下半部?
嵌入式内核为什么常用SLOB分配器?
进程调度的作用是什么?
系统调用的作用是什么?
五、课后作业
画图描述Linux内核五大核心机制之间的关系。
说明中断、软中断、tasklet、工作队列的区别与适用场景。
解释内核同步为什么在中断中只能用自旋锁。
简述虚拟内存作用及其在嵌入式中的价值。
查阅资料,说明CFS与RT调度器的区别。
六、本章总结
本章讲解嵌入式Linux内核八大核心机制:进程管理、调度、内存管理、中断处理、系统调用、同步互斥、定时器、工作队列。
内核是系统资源管理者,通过地址空间隔离保证稳定,通过调度保证响应速度,通过中断对接硬件,通过同步保证安全。
这些机制是理解内核裁剪、移植、驱动开发的基础,必须熟练掌握。
七、核心关键词
Linux内核、进程管理、调度、内存管理、中断、系统调用、同步机制、定时器、工作队列、内核空间
回顾总结
本课系统讲解嵌入式Linux内核的核心机制,是深入内核开发的必备理论基础。课程围绕内核最关键的八大机制展开,包括进程与线程管理、进程调度、内存管理、中断处理、系统调用、同步互斥、定时器延时、工作队列与内核线程。通过学习,理解内核作为硬件与应用中间层的核心作用,掌握用户空间与内核空间的隔离机制,理解MMU、虚拟地址、物理地址的关系。中断机制是嵌入式设备与内核交互的关键,课程重点说明上半部与下半部的区别,以及软中断、tasklet、工作队列的使用场景。同步与互斥机制保证多进程、多中断并发访问资源安全,明确自旋锁与互斥锁的使用原则。系统调用是应用程序进入内核的唯一合法入口,是驱动与应用交互的基础。调度机制决定系统实时性,CFS与RT调度器适用于不同场景。定时器与延时、工作队列与内核线程是内核实现定时、延后、后台任务的常用方式。本课所有内容均面向嵌入式场景,强调小体积、可裁剪、实时性、资源有限等特点,为后续内核配置、内核移植、设备驱动开发打下坚实理论基础。熟练掌握这些机制,能真正理解Linux运行原理,提升嵌入式系统开发与调试能力。
上一节课作业答案: 嵌入式C语言进阶(适配实战)模块一:基础入门
#include <stdio.h> // 温度转换函数:摄氏转华氏 float convert_c2f(float c) { return c * 1.8 + 32; } int main() { // 模拟传感器电压数组 float voltage[10] = {3.2, 3.5, 3.3, 3.6, 3.4, 3.1, 3.7, 3.2, 3.5, 3.6}; float sum = 0; int i; // 计算平均值 for (i = 0; i < 10; i++) { sum += voltage[i]; } float avg = sum / 10; printf("电压数组:"); for (i = 0; i < 10; i++) { printf("%.2f ", voltage[i]); } printf("\n平均电压:%.2fV\n", avg); // 模式控制演示 int mode = 2; switch (mode) { case 1: printf("设备模式:待机\n"); break; case 2: printf("设备模式:运行\n"); break; case 3: printf("设备模式:休眠\n"); break; default: printf("模式异常\n"); } // LED闪烁3次模拟 for (i = 0; i < 3; i++) { printf("LED 闪烁 %d\n", i + 1); } printf("LED 熄灭\n"); // 温度转换 float temp_c = 28.0; float temp_f = convert_c2f(temp_c); printf("温度:%.2f℃ → %.2f℉\n", temp_c, temp_f); return 0; }代码功能说明
该程序是嵌入式C语言基础综合实战作业,涵盖数组、循环、分支、函数、运算等核心知识点。程序定义电压数组并计算平均值,模拟传感器采集与数据处理;使用switch-case实现设备模式控制;通过for循环实现LED闪烁三次后熄灭;编写函数实现摄氏温度转华氏温度。代码贴近嵌入式真实场景,可用于练习变量、运算、流程控制、函数封装、数组遍历等基础能力,适合嵌入式入门者巩固C语言核心语法,为后续驱动开发打下基础。
注意事项
编译命令:gcc homework.c -o homework
数组下标不可越界,循环范围必须正确
函数必须先声明后调用
switch-case必须加break避免穿透
浮点数运算注意精度问题
变量必须初始化,避免随机值导致异常