我正在试验Raspberry Pi 3/4的实时功能。我编写了以下C++程序进行测试。
// Compile with:
// g++ realtime_task.cpp -o realtime_task -lrt && sudo setcap CAP_SYS_NICE+ep realtime_task
#include <cstdio>
#include <sched.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstdbool>
#include <chrono>
#include <algorithm>
using namespace std;
using namespace chrono;
using namespace chrono_literals;
int main(int argc, char **argv)
{
// allocate this process to the 4th core (core 3)
pid_t pid = getpid();
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(3, &cpuset);
int result = 0;
result = sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset);
if (result != 0)
{
perror("`sched_setaffinity` failed");
}
struct sched_param param;
// Use SCHED_FIFO
param.sched_priority = 99;
result = sched_setscheduler(pid, SCHED_FIFO, ¶m);
// Use SCHED_OTHER
// param.sched_priority = 0;
// result = sched_setscheduler(pid, SCHED_OTHER, ¶m);
if (result != 0)
{
perror("`sched_setscheduler` failed");
}
uint32_t count = 0;
uint32_t total_loop_time_us = 0;
uint32_t min_loop_time_us = numeric_limits<uint32_t>::max();
uint32_t avg_loop_time_us = 0;
uint32_t max_loop_time_us = 0;
while(true)
{
count++;
auto start = steady_clock::now();
auto loop_time_us = duration_cast<microseconds>(steady_clock::now() - start).count();
while(loop_time_us < 500)
{
loop_time_us = duration_cast<microseconds>(steady_clock::now() - start).count();
}
min_loop_time_us = min((uint32_t)loop_time_us, (uint32_t)min_loop_time_us);
total_loop_time_us += loop_time_us;
avg_loop_time_us = total_loop_time_us / count;
max_loop_time_us = max((uint32_t)loop_time_us, (uint32_t)max_loop_time_us);
if ((count % 1000) == 0)
{
printf("%u %u %u\r", min_loop_time_us, avg_loop_time_us, max_loop_time_us);
fflush(stdout);
}
}
return 0;
}
我已经用PREEMPT_RT补丁修补了内核。uname
报告5.15.84-v8+ #1613 SMP PREEMPT
,一切运行正常。
内核命令行参数有isolcpus=3 irqaffinity=0-2
来隔离第4个内核(core 3)并为上面的程序保留它,我可以在 htop 中看到我的程序是唯一运行在第4个内核(core 3)上的进程。
使用SCHED_FIFO
策略时,它报告以下最小、平均和最大循环时间...
MIN AVG MAX
500 522 50042
..和 htop 报告:
CPU▽ CTXT PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
3 1 37238 pi RT 0 4672 1264 1108 R 97.5 0.0 0:07.57 ./realtime_task
使用SCHED_OTHER
策略时,它报告以下最小、平均和最大循环时间...
MIN AVG MAX
500 500 524
..和 htop 报告:
CPU▽ CTXT PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
3 0 36065 pi 20 0 4672 1260 1108 R 100. 0.0 1:30.16 ./realtime_task
这和我期望的正好相反。我期望SCHED_FIFO
给予我更低的最大循环时间和更少的上下文切换。为什么我会得到这些结果呢?
1条答案
按热度按时间eoxn13cs1#
我在这里猜测一下。如果你运行SCHED_OTHER,但是把你的进程的优先级设置为非默认值,它会把这个进程提升到任何其他默认进程之上。所以你的任务基本上是一个其他所有其他的任务,因此占用cpu的时间会更长。这是文档所读到的:https://man7.org/linux/man-pages/man7/sched.7.html
计划其他:默认Linux分时调度SCHED_OTHER只能用于静态优先级0(即实时策略下的线程始终优先于SCHED_OTHER进程)。SCHED_OTHER是标准Linux分时调度程序,适用于不需要特殊实时机制的所有线程。