我们的产品正在运行 linux 2.6.32,并且我们有一些定期运行的用户空间进程 - “保持活动 - 类似”进程。我们对这些进程没有严格的要求——它们只需要在几秒钟内运行一次并刷新一些看门狗。
我们为这些进程提供了一个具有最大优先级的 RR 或 FIFO 调度类,然而,我们看到了许多误报——似乎它们在几秒钟内都没有获得 CPU。我觉得这很奇怪,因为我知道 Linux 虽然不是 RT 操作系统,但仍然可以产生非常好的性能(我看到人们在谈论几毫秒的订单)——我什至无法让该进程在 5 次中运行一次秒。
Linux RT 调度程序的逻辑似乎非常直接和简单,所以我怀疑这些进程被其他东西阻塞了——I/O 争用、中断或内核线程耗时太长——但现在我不太确定:我写了一个模拟这样一个过程的非常基本的程序 - 它每 1 秒唤醒一次,并测量自上次完成运行以来所花费的时间。据我了解,时间测量不包括任何 I/O 上的阻塞,因此此过程打印的结果反映了调度程序的行为:
#include <sched.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/param.h>
#include <time.h>
#define MICROSECONDSINASEC 1000000
#define MILLISECONDSINASEC 1000
int main()
{
struct sched_param schedParam;
struct timeval now, start;
int spent_time = 0;
time_t current_time;
schedParam.sched_priority = sched_get_priority_max(SCHED_RR);
int retVal = sched_setscheduler(0, SCHED_RR, &schedParam);
if (retVal != 0)
{
printf("failed setting RT sched");
return 0;
}
gettimeofday(&start, 0);
start.tv_sec -= 1;
start.tv_usec += MICROSECONDSINASEC;
while(1)
{
sleep(1);
gettimeofday(&now, 0);
now.tv_sec -= 1;
now.tv_usec += MICROSECONDSINASEC;
spent_time = MILLISECONDSINASEC * (now.tv_sec - start.tv_sec) + ((now.tv_usec - start.tv_usec) / MILLISECONDSINASEC);
FILE *fl = fopen("output_log.txt", "aw");
if (spent_time > 1100)
{
time(¤t_time);
fprintf(fl,"\n (%s) - had a gap of %d [msec] instead of 1000\n", ctime(¤t_time), spent_time);
}
fclose(fl);
gettimeofday(&start, 0);
}
return 0;
}
我在一夜之间在几台机器上运行了这个过程——包括那些不运行我们的产品的机器(只是普通的 Linux),我仍然看到了几秒钟的间隙——即使我确保进程 DID 获得了优先级——我不知道为什么 - 从技术上讲,这个进程应该抢占任何其他正在运行的进程,那么它怎么能等待这么长时间才能运行呢?
几点注意事项:
- 我主要在虚拟机上运行这些进程 - 所以可能会有来自管理程序的干预。但在过去,我也曾在物理机器上看到过这种行为。
- 制作过程 RT 确实极大地改善了结果,但并没有完全避免这个问题。
- 除了 Linux 迁移和看门狗进程(我不相信这会导致我的进程饥饿)之外,机器上没有运行其他 RT 进程。
我能做些什么?我觉得我在这里遗漏了一些非常基本的东西。
谢谢!