实时Linux之PREEMPT_RT篇

news/2024/10/17 23:27:04/

实时Linux主要有两类方案:

  • 单内核方案:对主线传统的Linux内核打入PREEMPT_RT补丁,使内核成为硬实时操作系统
  • 双内核方案:主线传统Linux内核+实时内核的双内核方案,常见的主流方式有:RT-Linux,RTAI、Xenomai。

本文重点讲解单内核PREEMPT_RT补丁方案。

概念基础

实时性

​ 实时分为硬实时和软实时,两者主要的区别主要就是就绪运行时间确定性。然后,主线Linux是软实时系统,加入实时补丁后将其改造为硬实时系统。

可抢占性

​ 实现实时内核很重要的特点是可抢占性,就绪的高优先级的任务能够抢占低优先级任务。Linux内核在2.6版本之后引入了抢占模型,支持任务抢占。

主线Linux支持如下三种抢占模型:

 (1) No Forced Preemption (Server): 传统的 Linux 抢占模型,面向吞吐量。系统调用返回和中断是唯一的抢占点。(2) Voluntary Kernel Preemption (Desktop):  此选项通过向内核代码 [. . . ] 以稍微降低吞吐量为代价。除了显式抢占点外,系统调用返回和中断返回都是隐式抢占点 (3) Preemptible Kernel (Low-Latency Desktop):  此选项通过使所有内核代码(不在临界区中执行的)可抢占来减少内核的延迟。隐式抢占点位于每个抢占禁用部分之后。

对于软实时的嵌入式系统来说,内核抢占模式配置为Preemptible Kernel (Low-Latency Desktop)最佳。

进程调度策略

​ Linux内核支持实时进程和非实时进程调度(无PREEMPT_RT补丁支持也是支持实时进程调度,只是软实时,有补丁后就是硬实时)。

​ 对于Linux进程任务来说,Linux 内核实现了多种调度策略。它们分为非实时和实时策略。调度策略已经在主线 Linux 中实现。

非实时策略:

  • SCHED_OTHER: 每个任务都有一个所谓的“nice值”。它是一个介于 -20(最高 nice 值)和 19(最低 nice 值)之间的值。任务执行时间的平均值取决于相关的 nice 值。
  • SCHED_BATCH: 此策略源自 SCHED_OTHER 并针对吞吐量进行了优化。
  • SCHED_IDLE: 它也是从 SCHED_OTHER 派生的,但它的值比 19 弱。

实时策略:

  • SCHED_FIFO: 任务的优先级介于 1(低)和 99(高)之间。在此策略下运行的任务将被调度,直到它完成或更高优先级的任务抢占它。
  • SCHED_RR: 此策略源自 SCHED_FIFO。与 SCHED_FIFO 的区别在于任务在定义的时间片的持续时间内运行(如果它没有被更高优先级的任务抢占)。一旦时间片用完,它可以被具有相同优先级的任务中断。时间片定义在 procfs (/proc/sys/kernel/sched_rr_timeslice_ms) 中导出。
  • SCHED_DEADLINE: 此策略实施全局最早deadline优先 (GEDF) 算法。在此策略下调度的任务可以抢占使用 SCHED_FIFO 或 SCHED_RR 调度的任何任务。

设置api:

sched_setscheduler()

PREEMPT_RT 实时补丁

打入PREEMPT_RT补丁,可实现硬实时内核。

PREEMPT_RT下载地址:http://cdn.kernel.org/pub/linux/kernel/projects/rt/

PREEMPT_RT补丁主要做了如下修改,修改背后的原理后续文章再深入描述:

  • 高分辨率定时器
  • 中断线程化
  • 自旋锁spinlock_t改为互斥锁rt_mutex,要使用自旋锁则使用raw_spinlock_t

打入PREEMPT_RT后内核抢占模型配置则会多了如下两项:

  • Preemptible Kernel (Basic RT): 这种抢占模型类似于“抢占内核(低延迟桌面)”模型。除了上面提到的属性外,线程中断处理程序是强制的(就像使用内核命令行参数时一样threadirqs)。该模型主要用于 PREEMPT_RT 补丁实现的替代机制的测试和调试。
  • Fully Preemptible Kernel (Real-Time): 除了少数选定的关键部分之外,所有内核代码都是可抢占的。线程中断处理程序是强制的。此外,还实现了几种替代机制,如睡眠自旋锁和 rt_mutex,以减少抢占禁用部分。此外,大的抢占禁用部分被单独的锁定结构取代。必须选择这种抢占模型以获得硬实时行为。

PREEMPT_RT 实时补丁的限制

​ 某些环境当前不能很好地与 Preempt-RT 配合使用。由于不兼容,CONFIG_PREEMPT_RT_FULL=y 禁用了几个功能。

禁用的配置选项,主要是虚拟化配置:

  • CONFIG_TRANSPARENT_HUGEPAGE
  • CONFIG_OPROFILE
  • CONFIG_XEN (arm64)
  • CONFIG_X86_POWERNOW_K8
  • CONFIG_BCACHE
  • CONFIG_HIGHMEM(mips,powerpc)
  • CONFIG_KVM_MPIC (powerpc)
  • CONFIG_RT_GROUP_SCHED
  • CONFIG_CPUMASK_OFFSTACK

PREEMPT_RT 实时补丁修改步骤

1、下载PREEMPT_RT补丁

对应内核版本选择PREEMPT_RT补丁的版本,不对应版本选择则可能出现不可预估性的问题或者打补丁出现大量冲突。

下载地址:http://cdn.kernel.org/pub/linux/kernel/projects/rt/

2、打补丁以及配置内核

传统的打补丁方法:

git apply xxx.patch
# 或
git am xxx.patch

传统的配置内核方法:

# 1、输入配置内核命令
make menuconfig
# 2、选中全功能实时抢占配置,保存退出
(*)Fully Preemptible Kernel (Real-Time)

因为我用的是yocto来构建系统,如下是我的菜谱追加文件

FILESEXTRAPATHS_prepend := "${THISDIR}/preempt-rt-patch:" ## 存放补丁和配置的目录
PATCHTOOL = "git"
SRC_URI += "file://preempt_full.cfg"        ## 配置片段
SRC_URI += "file://patch-5.10.8-rt24.patch" ## 补丁

preempt_full.cfg配置片段:

CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_PREEMPT_LAZY=y
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_RT=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_DELAY=500
CONFIG_EXPERT=y
# CONFIG_SGETMASK_SYSCALL is not set
# CONFIG_DEBUG_RSEQ is not set
CONFIG_EMBEDDED=y
# CONFIG_PC104 is not set
# CONFIG_SLUB_MEMCG_SYSFS_ON is not set
# CONFIG_SUSPEND_SKIP_SYNC is not set
# CONFIG_DPM_WATCHDOG is not set
# CONFIG_FIRMWARE_MEMMAP is not set
# CONFIG_VIRTUALIZATION is not set
CONFIG_ARCH_SUPPORTS_RT=y
# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
# CONFIG_PCIE_BUS_TUNE_OFF is not set
CONFIG_PCIE_BUS_DEFAULT=y
# CONFIG_PCIE_BUS_SAFE is not set
# CONFIG_PCIE_BUS_PERFORMANCE is not set
# CONFIG_PCIE_BUS_PEER2PEER is not set
# CONFIG_WIRELESS_WDS is not set
# CONFIG_TTY_PRINTK is not set
# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set
# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set
# CONFIG_SND_SOC_SOF_DEVELOPER_SUPPORT is not set
CONFIG_MXC_GPU_VIV=y
# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set
# CONFIG_DEBUG_MEMORY_INIT is not set

3、编译以及烧写镜像

make Image

4、下载实时测试工具套件

运行下面指令下载实时测试工具,然后按照你的环境对其交叉编译:

git clone git://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git

5、实时性测试

实时性测试主要有两个点:模拟负载和cyclictest。
模拟负载就是通过运行一些程序让系统处于高负载的状态。
cyclictest就是开源的Linux实时性测试工具。
模拟负载有多种方式,比如stress、stress-ng、hackbench、脚本模拟。
如下是我模拟负载脚本(stress_loades.sh ),内部使用了dd、hackbench、ping、taskset、cyclictest命令,其中cyclictest、hackbench是上面下载的实时测试工具套件内部自带的,其他三个命令也是一般系统都会自带的:

#!/bin/bash# 如果参数小于1
if [ "$1" == "-h" ]
then echo "example:"echo "		  ./stress_loades.sh [Level]"echo "option:"echo "		  1: heavy cpu load"echo "		 -h: help "exit 0
fi# 如果参数等于1
if [ "$1" == "1" ]
thenwhile true; do dd if=/dev/zero of=bigfile bs=1024000 count=1024; done > /dev/null &while true; do killall hackbench; sleep 5; done > /dev/null &while true; do ./hackbench 20; done > /dev/null &	
fitaskset -c 0 ping -l 65535 -q -s 10 -f localhost > /dev/null &
taskset -c 1 ping -l 65535 -q -s 10 -f localhost > /dev/null &
taskset -c 2 ping -l 65535 -q -s 10 -f localhost > /dev/null &
taskset -c 3 ping -l 65535 -q -s 10 -f localhost > /dev/null &while true; do taskset -c 3 du / ; done  > /dev/null &time ./cyclictest -t50 -p 80 -i 10000 -s -l 100000000000 -d 86400  -a 3 > /dev/null &

实时测试脚本(cyclictest.sh):

#!/bin/bash
./cyclictest -S -p 99 -i 1000 -D 5m -m -s -h400 -q >no_load_output ./stress_loades.sh ./cyclictest -S -p 99 -i 1000 -D 5m -m -s -h400 -q >light_load_output./stress_loades.sh 1./cyclictest -S -p 99 -i 1000 -D 5m -m -s -h1000 -q >heavy_load_output 

这里为了展示效果,我只运行了5分钟测试,实际上应以产品的应用场景时长做测试,这样比较能反应其实时稳定性。

6、实时测试总结

我测试 Voluntary Kernel Preemption (Desktop)、Preemptible Kernel (Low-Latency Desktop)、Fully Preemptible Kernel (Real-Time) 三种抢占模型在无负载、一般负载、超重负载下的实时性。
在无负载的情况下,三种抢占模型基本上都能稳定实时响应,在一般负载和超重负载下,Voluntary和Preemptible模型出现了比较大延时抖动,其中Voluntary在一般负载下,最大延时达到395us,在超重负载下最大延时达到2599us,而Preemptible在一般负载下,最大延时达到241us,但是在超重负载下,最大延时达到了11920us。然而Fully Preemptible模型,在三种负载都表现出稳定实时性能,无负载下,最大延时49us,一般负载下,最大延时55us,超重负载下,最大延时79us。
由于测试的时间短以及实时性也跟处理器性能有关系,因此该测试仅作为简单参考。
最后,测试结果的直方图如下:

Voluntary Kernel Preemption (Desktop)抢占模型:

无负载:

一般负载:
在这里插入图片描述

超重负载:
在这里插入图片描述

Preemptible Kernel (Low-Latency Desktop)抢占模型:

无负载:
在这里插入图片描述

一般负载:
在这里插入图片描述

超重负载:
在这里插入图片描述

Fully Preemptible Kernel (Real-Time) 抢占模型:

无负载:
在这里插入图片描述

一般负载:
在这里插入图片描述

超重负载:
在这里插入图片描述

实时应用程序开发

对于有实时需求的应用程序,一般需要设置调度策略,优先级等等参数。一般常用的api函数如下:

sched_setscheduler()
pthread_attr_setschedpolicy()
pthread_attr_setschedparam()
pthread_attr_setinheritsched()

示例如下:

/* POSIX Real Time Example* using a single pthread as RT thread	*/#include <limits.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>void *thread_func(void *data)
{/* Do RT specific stuff here */return NULL;
}int main(int argc, char* argv[])
{struct sched_param param;pthread_attr_t attr;pthread_t thread;int ret;/* Lock memory */if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {printf("mlockall failed: %m\n");exit(-2);}/* Initialize pthread attributes (default values) */ret = pthread_attr_init(&attr);if (ret) {printf("init pthread attributes failed\n");goto out;}/* Set a specific stack size  */ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);if (ret) {printf("pthread setstacksize failed\n");goto out;}/* Set scheduler policy and priority of pthread */ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);if (ret) {printf("pthread setschedpolicy failed\n");goto out;}param.sched_priority = 80;ret = pthread_attr_setschedparam(&attr, &param);if (ret) {printf("pthread setschedparam failed\n");goto out;}/* Use scheduling parameters of attr */ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);if (ret) {printf("pthread setinheritsched failed\n");goto out;}/* Create a pthread with specified attributes */ret = pthread_create(&thread, &attr, thread_func, NULL);if (ret) {printf("create pthread failed\n");goto out;}/* Join the thread and wait until it is done */ret = pthread_join(thread, NULL);if (ret)printf("join pthread failed: %m\n");out:return ret;
}

FAQ

Scheduling - RT throttling

实时任务具有较高优先级,Linux内核优先调度高优先级任务。

如果实时应用程序中的编程失败会导致整个系统挂起,这种失败可能就像调用了一个“while(true){}”循环。

当实时应用程序具有尽可能高的优先级并使用 SCHED_FIFO 策略进行调度时,没有其他任务可以抢占它。

这会导致系统阻塞所有其他任务并以 100% 的 CPU 负载调度此循环。

实时节流是一种通过限制每个实时任务的周期执行时间来避免这种情况的机制。

这些设置被导出到 proc 文件系统中。

默认设置为:

# cat /proc/sys/kernel/sched_rt_period_us
1000000
# cat /proc/sys/kernel/sched_rt_runtime_us
950000

如果要使实时任务的 CPU 使用率仅达到 50% ,可以使用以下命令更改这些值:

# echo 2000000 > /proc/sys/kernel/sched_rt_period_us 
# echo 1000000 > /proc/sys/kernel/sched_rt_runtime_us

如果想要禁用实时节流, 通过将 -1 写入 sched_rt_runtime_us 来自动完成的:

# echo -1 > /proc/sys/kernel/sched_rt_runtime_us

http://www.ppmy.cn/news/123312.html

相关文章

NSIS 系统插件

原文&#xff1a;https://nsis.sourceforge.io/Docs/System/System.html 抄抄写写的翻译 NSIS 系统插件 目录 • 介绍 • 可用功能 o 内存相关功能 o 调用函数 o 64 位函数 • 常见问题 介绍 系统插件使开发人员能够调用任何 DLL 的任何…

Android 内核源码编译记录

注&#xff1a;此处内容总结自google官网&#xff1a;AOSP 编译内核。编译完成后刷机部分参考自其他大佬的文章。文中末尾提供了上传至CSDN的msm内核和Aarch64gcc工具 的下载链接&#xff0c;不想从官网下载的可以直接使用这个资源。 一.简介 1. 环境 手机&#xff1a;pixel…

Shell 编程

Shell 编程 1.什么是shell shell是一个命令解释器, 将人类输入高级语言, 通过 Shell程序 转换为 二进制、 shell分为两种使用方式: ​ 交互: 登录 执行命令 退出 ​ 非交互: 执行某个文件, 文件中都是一推命令, 整个文件从上往下依次执行 2.什么是shell 脚本 (1) 将系统命令堆积…

网络安全学习中的工具

1> Nmap Nmap&#xff0c;也就是Network Mapper&#xff0c;最早是Linux下的网络扫描和嗅探工具包。 系统管理员可以利用nmap来探测工作环境中未经批准使用的服务器&#xff0c;但是黑客会利用nmap来搜集目标电脑的网络设定&#xff0c;从而计划攻击的方法。 其基本功能有三…

左耳听风——笔记二:程序员练级攻略

文章目录 入门篇操作系统入门 Linux 编程技能专业基础篇编程语言Java 语言学习 Go 语言 理论学科数据结构和算法其它理论基础知识 系统知识C10K 问题实践项目 软件设计篇编程范式一些软件设计的相关原则一些软件设计的读物 高手成长篇Linux 系统、内存和网络&#xff08;系统底…

iOS 16 UIResponderForwarderWantsForwardingFromResponder Crash问题解决方案

背景 最近后台统计发现有一个随机的Crash&#xff0c;引起了我们的关注 从操作系统来看&#xff0c;都是iOS 16 系统 崩溃堆栈如下&#xff1a; Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x0000000000000001, 0x00000001daa1808c Termination Reason: …

Pentest Wiki Part3 渗透工具

渗透测试工具 渗透测试工具 攻击可能是渗透测试中最迷人的部分之一了&#xff0c;但它通常是用暴力破解而不是精确制导来完成的。只有当你知道针对目标的一个特定漏洞很可能会成功的时候&#xff0c;你才应该发起一次攻击。即在利用漏洞之前&#xff0c;您应该知道目标是存在该…

Elasticsearch + Logstash + Kibana 日志分析系统搭建

Elasticsearch Logstash Kibana 日志分析系统搭建 一、简介1.1 Elasticsearch、Logstash 和 Kibana 简介1.2 日志分析系统的意义 二、日志分析系统技术架构2.1 Logstash2.2 Elasticsearch2.3 Kibana 三、环境搭建3.1 下载安装 Elasticsearch Logstash Kibana3.1.1 Elasticsea…