CentOS8实时FIFO进程收不到XCPU信号

CentOS8 real-time FIFO process not receiving XCPU signal

背景

我有一个非常精确的程序,我需要为它使用实时调度策略。该程序应该做什么是不可能的。不过,在编写实际程序之前,我想稍微测试一下 - 实时和“正常”调度策略之间的一些差异(例如,我注意到 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;
}

结果是 - 进程不断占用 CPU、运行 和 运行 的 90% 以上,并且没有看到接收到信号。实际上,我将程序 运行 保留了大约 15 分钟,但什么也没有发生——进程没有被杀死。我的意思是,FIFO 调度不应该在 运行 时删除线程,对吗?这就是 Round Robin 所做的,所以我不太明白是什么导致了这种现象。我的线程是否在我不知情的情况下进入睡眠状态?
将截止时间设置为 2^63 - (1, 2, 3) 数字的 DEADLINE 调度是否会比当前的 FIFO 解决方案更好?大多数时候我只是想为自己获得大部分 CPU,因为除了我自己的进程之外真的什么都不会使用 CPU(唯一的区别是实时调度策略给一些额外的好处,其中一个我在开头注意到并描述过 - 提高了 nanosleep 的精度。还有其他好处吗?)。

好的,我找到答案了。
问题在于 RTIME 的软硬限制。我认为默认情况下它们非常低,但现在我仔细检查以确保。软硬限制均为 2^63 个数字。在将软限制降低到 1e6 和硬限制到 1e7 之后,我的进程开始每秒接收 XCPU 信号。使用 getrlimitsetrlimit 函数检查并降低(有关更多信息,请参阅 man)。