Linux 移植与实时特性解析
1. Linux 移植到自定义板卡
在将 Linux 移植到基于 Linux 支持的 CPU 的自定义板卡时,我们可以以一个已支持的硬件平台的工作参考配置为基础,进行相应的修改。下面以 PowerPC 架构为例,介绍将 Linux 移植到名为 PowerDNA 的自定义平台的具体步骤。
1.1 移植步骤
-
添加配置选项
:在
...arch/ppc/Kconfig中添加新的配置选项。为新的 PowerDNA 端口添加的配置选项如下:
config POWERDNA
bool "United Electronics Industries PowerDNA"
select PPC_MPC52xx
help
Support for the UEI PowerDNA board
此 Kconfig 条目添加在 LITE5200 条目下方,因为它们相关。当用户选择 POWERDNA 时,会自动选择 CONFIG_PPC_MPC52xx 配置选项,并定义一个新的配置选项 CONFIG_POWERDNA 来驱动构建配置。
-
复制基础文件
:将 Lite5200 平台文件作为基线,复制
lite5200.*
到
powerdna.*
,即复制
lite5200.c
到
powerdna.c
,
lite5200.h
到
powerdna.h
。
-
编辑新文件
:根据硬件平台的硬件规格、原理图和其他数据,编辑新的
powerdna.*
文件,使其适合硬件。
-
修改 Makefile
:编辑
.../arch/ppc/Makefile
以有条件地包含
powerdna.o
,添加如下一行:
obj-$(CONFIG_POWERDNA) += powerdna.o
- 编译、加载和调试 :完成上述步骤后,进行编译、加载和调试新内核。
1.2 涉及的文件
移植过程中添加或修改的文件如下:
| 文件路径 | 说明 |
| — | — |
| linux-2.6.14/arch/ppc/configs/powerdna_defconfig | 默认配置文件,可通过
$ make ARCH=ppc CROSS_COMPILE=<cross-prefix> powerdna_defconfig
启用快速内核配置 |
| linux-2.6.14/arch/ppc/Kconfig | 配置文件,添加了 POWERDNA 相关配置选项 |
| linux-2.6.14/arch/ppc/platforms/Makefile | Makefile 文件,添加了对 POWERDNA 内核配置的支持 |
| linux-2.6.14/arch/ppc/platforms/powerdna.c | 平台初始化文件 |
| linux-2.6.14/arch/ppc/platforms/powerdna.h | 平台头文件 |
| linux-2.6.14/drivers/net/fec_mpc52xx/fec.c | 网络驱动文件 |
| linux-2.6.14/drivers/net/fec_mpc52xx/fec.h | 网络驱动头文件 |
| linux-2.6.14/drivers/net/fec_mpc52xx/fec_phy.h | 网络物理层驱动头文件 |
| linux-2.6.14/include/asm-ppc/mpc52xx.h | 汇编头文件 |
1.3 主要修改点
powerdna.[c|h]
文件和 FEC(快速以太网控制器)层的修改是移植的核心。与衍生文件
lite5200.c
相比,主要有两个方面的修改:
-
禁用 PCI
:PowerDNA 设计中未使用 PCI,因此需要进行一些小的调整。
-
以太网物理层芯片
:PowerDNA 设计中采用了非管理型以太网物理层芯片,需要在硬件设置和 FEC 层进行细微更改。
2. 实时 Linux 概述
在早期,Linux 在实时应用方面并不被看好,但随着音频和多媒体应用的发展,实时 Linux 有了很大的进步。下面介绍实时的概念、Linux 调度和内核抢占等相关内容。
2.1 实时的定义
实时可分为软实时和硬实时:
-
软实时
:操作有截止时间,但错过截止时间只会降低体验质量,不会导致致命后果。例如,在桌面工作站上编辑文档或播放音乐时,若出现一定延迟,虽会影响体验,但不会造成灾难性结果。一般来说,人类难以察觉几十毫秒以下的延迟,但音乐家可能对更小的延迟更敏感。
-
硬实时
:错过截止时间往往会导致灾难性结果。例如,嵌入式设备控制喷气式飞机发动机的燃油流量时,错过对飞行员输入或操作特性变化的响应截止时间,可能会导致灾难性后果。需要注意的是,截止时间的长短与实时特性无关,如原子时钟的计时处理,只要在 1 秒窗口内处理完一个计时,数据就仍然有效,错过处理可能会使全球定位系统出现较大偏差。
2.2 Linux 调度
UNIX 和 Linux 的进程调度设计注重公平性,调度器会尽力在所有需要 CPU 的进程之间分配可用资源,保证每个进程都能取得进展。然而,实时进程需要在准备好运行后尽快运行,实时意味着具有可预测和可重复的延迟。
2.3 延迟
实时进程通常与物理事件相关,如来自外围设备的中断。Linux 系统中的延迟组件主要包括:
-
中断延迟
:从接收到要处理的中断(时间 t0)到中断被处理并将控制权传递给中断服务例程(ISR,时间 t1)的时间,几乎完全由最大中断关闭时间决定。
-
调度延迟
:从 ISR/底半部处理完成唤醒等待数据的用户空间进程(时间 t2)到实时进程被调度器选中运行并获得 CPU(时间 t3)的时间,主要受等待 CPU 的进程数量和它们之间的优先级影响。为进程设置实时属性可以使其比普通 Linux 进程具有更高的优先级,假设它是等待 CPU 的最高优先级实时进程,就会被选中运行。
下面是 Linux 系统延迟组件的 mermaid 流程图:
graph LR
A[接收到中断 t0] --> B[中断被处理 t1]
B --> C[ISR/底半部处理完成 t2]
C --> D[实时进程被调度运行 t3]
3. 内核抢占
在早期的 Linux 1.x 版本中,内核不支持抢占。这意味着当用户空间进程请求内核服务时,在该进程阻塞(进入睡眠状态)等待某些资源(通常是 I/O)或内核请求完成之前,其他任务无法被调度运行。而使内核可抢占意味着当一个进程在内核中运行时,另一个优先级更高的进程可以抢占它并获得 CPU 使用权。
3.1 抢占的障碍
要使内核完全可抢占,关键在于识别内核中所有必须防止抢占的地方,即内核中的关键部分,在这些地方不允许发生抢占。例如,当一个进程在内核中执行文件系统操作时,可能需要写入表示文件系统上文件的内核数据结构。为了保护该数据结构不被损坏,进程必须锁定其他进程对共享数据结构的访问,示例代码如下:
...
preempt_disable();
...
/* Critical section */
update_shared_data();
...
preempt_enable();
...
如果不这样保护共享数据,更新共享数据结构的进程可能在更新过程中被抢占,若另一个进程尝试更新相同的共享数据,数据损坏几乎是必然的。
3.2 抢占模型
- 早期模型 :早期的内核抢占解决方案是在已知可以安全抢占当前执行线程的内核代码的战略位置放置检查点,如系统调用的入口和出口、某些内核锁的释放以及中断处理返回等位置。在这些点使用类似以下的代码进行抢占检查:
...
/*
* This code is executed at strategic locations within
* the Linux kernel where it is known to be safe to
* preempt the current thread of execution
*/
if (kernel_is_preemptable() && current->need_resched)
preempt_schedule();
...
/*
* This code is in .../kernel/sched.c and is invoked from
* those strategic locations as above
*/
#ifdef CONFIG_PREEMPT
asmlinkage void preempt_schedule(void)
{
while (current->need_resched) {
ctx_sw_off();
current->state |= TASK_PREEMPTED;
schedule();
current->state &= ~TASK_PREEMPTED;
ctx_sw_on_no_preempt();
}
}
#endif
...
这种方法虽然降低了 Linux 系统的延迟,但并不理想。
-
改进模型
:为了进一步显著降低延迟,理想的可抢占内核应该是:Linux 内核在任何地方都完全可抢占,仅在关键部分禁用抢占。这是内核开发者自原始可抢占内核补丁系列以来一直努力的方向,但这并非易事,需要仔细分析整个内核源代码,确定必须保护免受并发影响的数据,并仅在这些位置禁用抢占。通过对内核进行延迟测量,找出延迟最长的代码路径并进行修复,较新的 Linux 2.6 内核可以配置为适用于低延迟应用。
3.3 SMP 内核
创建高效的多处理器架构的许多工作也对实时应用有益。SMP(对称多处理)架构比单处理器架构更复杂,因为需要额外保护并发问题。在单处理器模型中,同一时间只有一个任务可以在内核中执行,保护并发只需防止中断或异常处理。而在 SMP 模型中,除了中断和异常处理的威胁外,内核中可能有多个执行线程。早期的 SMP 内核使用大内核锁(BKL)来保护并发,但这导致了调度效率低下,一个 CPU 可能会长时间闲置。用更细粒度的锁替换 BKL,仅围绕实际需要保护的共享数据进行锁定,可显著降低抢占延迟。
3.4 抢占延迟的来源
实时系统必须能够在指定的时间上限内处理其实时任务,实现一致的低抢占延迟对实时系统至关重要。抢占延迟的两个主要来源是中断上下文处理和禁用中断的关键部分处理。已经有大量工作致力于减小关键部分的大小(从而缩短持续时间),因此中断上下文处理成为了下一个需要解决的挑战,Linux 2.6 实时补丁解决了这个问题。
4. 实时内核补丁
实时内核补丁是为了进一步降低 Linux 内核的延迟,以满足实时应用的需求。下面将详细介绍实时内核补丁的相关内容。
4.1 补丁的作用
实时内核补丁主要解决了 Linux 内核在实时应用中的延迟问题,特别是针对中断上下文处理和关键部分处理的延迟。通过对内核进行修改,使得内核能够更快速地响应实时任务,减少任务处理的延迟。
4.2 补丁的实现方式
实时内核补丁的实现通常涉及以下几个方面:
-
中断处理优化
:对中断处理机制进行优化,减少中断延迟。例如,采用更快的中断响应方式,提高中断处理的效率。
-
关键部分优化
:对内核中的关键部分进行优化,减少关键部分的执行时间。可以通过使用更高效的数据结构和算法,或者对关键代码进行优化来实现。
-
调度算法改进
:改进调度算法,使得实时任务能够更优先地获得 CPU 资源。例如,采用实时调度策略,如 FIFO(先进先出)和 RR(轮转)调度算法,确保实时任务的及时执行。
4.3 补丁的应用
要应用实时内核补丁,通常需要以下步骤:
1.
下载补丁文件
:从官方网站或其他可靠来源下载适合当前内核版本的实时内核补丁文件。
2.
备份内核
:在应用补丁之前,务必备份当前的内核,以防出现问题。
3.
应用补丁
:使用
patch
命令将补丁文件应用到内核源代码中。例如:
patch -p1 < path/to/rt-patch.patch
-
配置内核
:重新配置内核,启用实时相关的选项。可以使用
make menuconfig或其他配置工具进行配置。 - 编译和安装内核 :编译并安装新的内核。例如:
make
make modules_install
make install
5. 实时内核调试
调试实时内核是确保实时系统正常运行的重要步骤。下面介绍一些调试实时内核的方法和技巧。
5.1 调试工具
常用的调试工具包括:
-
gdb
:GNU 调试器,可以用于调试内核代码。通过 gdb 可以设置断点、单步执行代码、查看变量值等。
-
kgdb
:内核级的 gdb 调试器,专门用于调试内核。kgdb 可以通过串口或网络连接到目标系统,对内核进行调试。
-
SystemTap
:一种动态跟踪工具,可以在不修改内核源代码的情况下对内核进行跟踪和调试。SystemTap 可以用于收集内核的运行时信息,如函数调用、变量值等。
5.2 调试步骤
调试实时内核的一般步骤如下:
1.
确定问题
:首先要确定需要调试的问题,例如,实时任务的延迟过高、系统崩溃等。
2.
设置调试环境
:根据问题的性质,选择合适的调试工具,并设置好调试环境。例如,如果需要调试内核代码,可以使用 gdb 或 kgdb;如果需要收集系统的运行时信息,可以使用 SystemTap。
3.
重现问题
:尝试重现问题,以便能够对问题进行调试。可以通过模拟实时任务的负载、触发特定的事件等方式来重现问题。
4.
分析问题
:使用调试工具对问题进行分析,找出问题的根源。例如,通过设置断点、查看变量值等方式,逐步排查问题。
5.
解决问题
:根据分析结果,对问题进行解决。可能需要修改内核代码、调整系统配置等。
6.
验证解决方案
:验证解决方案是否有效,确保问题得到解决。可以再次重现问题,检查系统的运行情况。
5.3 调试注意事项
在调试实时内核时,需要注意以下几点:
-
实时性影响
:调试过程可能会对系统的实时性产生影响。例如,设置断点、单步执行代码等操作会增加系统的延迟。因此,在调试过程中要尽量减少对实时任务的影响。
-
数据一致性
:在调试过程中,要注意数据的一致性。例如,在查看变量值时,要确保变量的值是在正确的上下文中获取的。
-
安全性
:调试内核是一项危险的操作,可能会导致系统崩溃或数据丢失。因此,在调试之前要务必备份重要的数据,并确保调试环境的安全性。
6. 总结
实时 Linux 在现代嵌入式系统和实时应用中扮演着越来越重要的角色。通过了解实时的概念、Linux 调度、内核抢占、实时内核补丁和调试等方面的知识,可以更好地开发和调试实时系统。
在将 Linux 移植到自定义板卡时,要以已支持的硬件平台为基础,按照一定的步骤进行移植,并注意对关键文件和代码的修改。在开发实时系统时,要选择合适的实时内核补丁,优化内核配置,以降低系统的延迟。同时,要掌握调试实时内核的方法和技巧,确保实时系统的正常运行。
以下是一个总结的表格,展示了实时 Linux 相关的关键知识点:
| 知识点 | 描述 |
| — | — |
| 实时定义 | 分为软实时和硬实时,软实时错过截止时间降低体验质量,硬实时错过截止时间可能导致灾难性后果 |
| Linux 调度 | 注重公平性,与实时进程尽快运行的需求相悖 |
| 延迟 | 包括中断延迟和调度延迟,影响实时进程的响应时间 |
| 内核抢占 | 使内核可被高优先级进程抢占,提高实时任务的响应能力 |
| 实时内核补丁 | 降低内核延迟,通过优化中断处理、关键部分和调度算法实现 |
| 实时内核调试 | 使用 gdb、kgdb、SystemTap 等工具,按照一定步骤进行调试 |
下面是一个实时 Linux 开发流程的 mermaid 流程图:
graph LR
A[需求分析] --> B[选择硬件平台]
B --> C[移植 Linux 内核]
C --> D[应用实时内核补丁]
D --> E[配置内核]
E --> F[开发实时应用]
F --> G[调试实时内核和应用]
G --> H[优化系统性能]
H --> I[部署系统]
通过以上的介绍,希望能够帮助大家更好地理解和应用实时 Linux 技术,开发出高效、稳定的实时系统。
Linux移植与实时特性详解
超级会员免费看
4385

被折叠的 条评论
为什么被折叠?



