这些教程通常需要一个终端用于执行教程应用程序,至少一个额外的终端用于执行各种影响应用程序行为的压力测试,或用于监控以捕获其操作的统计信息。最好通过 SSH 远程访问执行教程的系统,以避免桌面 GUI 中断影响测量结果(非Xenomai内核)。
教程包括:
使用代码设置CPU亲和性
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
int main() {
pthread_t thread = pthread_self(); // 获取当前线程
cpu_set_t cpµset; // 定义 CPU 集合
int cpu = 2; // 要绑定的 CPU 核心
CPU_ZERO(&cpµset); // 清除 CPU 集合
CPU_SET(cpu, &cpµset); // 将 CPU 2 添加到集合中
// 设置线程的 CPU 亲和性
if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpµset) != 0) {
perror("设置 CPU 亲和性失败");
return 1;
}
printf("线程已成功绑定到 CPU %d。\n", cpu);
return 0;
}
使用命令行设置CPU亲和性
# 可以启动一个程序并将其绑定到特定的 CPU(比如 CPU 0 和 CPU 1)
sudo taskset -c 0,1 my_program
开始在CPU2上执行应用程序(非隔离)
latency -c2 -t0 -p 100 -P 99 -h
平均值为 30µs
开始在CPU1上执行应用程序(隔离)
latency -c1 -t0 -p 100 -P 99 -h
平均值为 10µs
页面错误(Page faults)会对确定性产生负面影响。内存锁定可以防止应用程序中大部分甚至全部页面错误的发生。
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h> // 包含 mlockall 函数的头文件
#include <unistd.h> // 包含 sleep 函数的头文件
int main() {
// 使用 mlockall 锁定进程的所有内存到物理内存中
// MCL_CURRENT: 锁定当前内存页
// MCL_FUTURE: 锁定未来分配的内存页
if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
perror("内存锁定失败");
return 1;
}
printf("内存已锁定,防止交换到磁盘。\n");
// 模拟程序运行,期间内存保持锁定
for (int i = 0; i < 10; i++) {
printf("程序运行中...\n");
sleep(1); // 休眠 1 秒
}
// 解除内存锁定
if (munlockall() != 0) {
perror("解除内存锁定失败");
return 1;
}
printf("内存锁定已解除。\n");
return 0;
}
可以通过健康监测工具健康进程的Page faults次数
sudo sjournal_run 1h
实时应用程序会抢占其他非实时的应用程序。优先级参数设置执行工作负载的线程优先级。当此参数被省略或设置为零时,线程不是实时的。将其设置为99可确保RT执行。
使用代码设置为实时线程优先级
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
// 线程函数
void* thread_func(void* arg) {
while (1) {
// 模拟一些工作
sleep(1);
}
return NULL;
}
int main() {
pthread_t thread;
struct sched_param param;
int policy = SCHED_FIFO; // 使用 FIFO 实时调度策略
int max_priority, min_priority;
// 创建线程
if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
perror("无法创建线程");
return 1;
}
// 获取 SCHED_FIFO 策略的最大和最小优先级
max_priority = sched_get_priority_max(SCHED_FIFO);
min_priority = sched_get_priority_min(SCHED_FIFO);
printf("SCHED_FIFO 最大优先级: %d, 最小优先级: %d\n", max_priority, min_priority);
// 设置线程的优先级(选择一个合适的值,如最大优先级)
param.sched_priority = max_priority;
// 设置线程的调度策略和优先级
if (pthread_setschedparam(thread, policy, ¶m) != 0) {
perror("无法设置线程优先级");
return 1;
}
printf("线程已设置为实时优先级 (SCHED_FIFO, 优先级: %d)\n", param.sched_priority);
// 等待线程结束
pthread_join(thread, NULL);
return 0;
}
使用命令行设置线程为实时线程
# 将正在运行的进程转换为实时调度策略
sudo chrt -f 99 <priority> <pid>
# 以实时调度策略启动新进程
sudo chrt -f 99 <priority> <command>
使用下面的命令查看设置是否成功
chrt -p <pid>