【发布时间】:2021-02-03 02:05:40
【问题描述】:
背景
我有一个非常精确的计划,我需要为此使用实时调度策略。该程序应该做什么是不可能的。不过,在编写实际程序之前,我想测试一些东西——实时和“正常”调度策略之间的一些差异(例如,我注意到 nanosleep 的实时 FIFO 精度提高了 10 倍调度和 99 优先级),当然还有 SIGXCPU 信号,如果它一次超过软允许的 CPU 时间,则应该将其发送到实时进程。我没有收到它,即使我的进程正在无限循环地消耗 CPU 时间。
环境
我使用托管在 vultr 上的 CentOS8 - 1 个内核、512MB RAM、最新版本的内核和每个软件包。在没有我的实时进程运行的情况下,top 显示 2-3 个进程正在运行(systemd 是主要进程)和 80 多个睡眠。活动进程似乎都有正常的调度策略,优先级设置为 20,这是最低的。
我的实时进程的代码如下所示:
#define _GNU_SOURCE
// most of these are useless yes, were used before for testing
// and I just did not care to remove them, but that shouldn't change anything, right
#include <sched.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdatomic.h>
#include <signal.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
static uint64_t GetTimeoutTime(const uint64_t nanoseconds) {
struct timespec tp = { .tv_sec = 0, .tv_nsec = 0 };
(void) clock_gettime(CLOCK_MONOTONIC, &tp);
return (uint64_t)(tp.tv_sec) * 1000000000 + (uint64_t)(nanoseconds / 1000000000) * 1000000000 + (uint64_t)(tp.tv_nsec) + nanoseconds - (uint64_t)(nanoseconds / 1000000000) * 1000000000;
}
static int siga(int signum, void (*handler)(int)) {
return sigaction(signum, &((struct sigaction){ .sa_handler = handler, .sa_flags = 0, .sa_mask = 0 }), NULL);
}
static void xcpu(int sig) {
puts("xcpu called");
(void) pthread_yield(); // to not get killed
}
int main() {
uint64_t g = 0;
uint64_t t1, t2;
int err = siga(SIGXCPU, xcpu);
if(err != 0) {
puts("e");
printf("%d\n", err);
}
if(sched_setscheduler(getpid(), SCHED_FIFO, &((struct sched_param){ .sched_priority = 99 })) != 0) {
puts("err");
}
while(1) {
t1 = GetTimeoutTime(0); // just some stuff to make the process busy
t2 = GetTimeoutTime(0) - t1; // I was using this code before, thus left it there
g += t2;
}
printf("avg %lf\n", (double)(g) / 10000.0); // just to make it seem as g is not useless
return 0;
}
结果是 - 进程不断占用超过 90% 的 CPU,运行和运行,并且没有看到收到任何信号。实际上,我让程序运行了大约 15 分钟,但什么也没发生——进程没有被杀死。我的意思是,FIFO调度不应该在线程运行时删除它们,对吗?这就是 Round Robin 所做的,所以我不太明白是什么导致了这种现象。我的线程是否在我不知情的情况下进入睡眠状态?
将截止时间设置为某个 2^63 - (1, 2, 3) 数字的 DEADLINE 调度会比当前的 FIFO 解决方案更好吗?我只是想在大多数时候为自己获得大部分 CPU,因为实际上除了我自己的进程将使用 CPU(唯一的区别是实时调度策略提供了一些好处,其中之一)我在开头注意到并描述了 - 提高 nanosleep 的精度。还有其他好处吗?)。
【问题讨论】:
-
Someone else says 你需要请求它。