如何从命令行中使用SCHED_RR策略运行程序?

默认情况下,Linux 上的程序以时间共享(TS 策略)运行。如何在 Linux 命令行中使用 SCHED_RR 策略运行程序?
感谢提供关于 chrt(1) 命令的信息。 我已经使用该命令以 RR 策略运行 Firefox, 但正如您在下面看到的,只有 Firefox 的主线程以 RR 策略运行。 您能告诉我如何使 Firefox 的所有其他线程也以 RR 策略运行吗?
$ ps -Lo pid,tid,class 2051
  PID   TID CLS
 2051  2051 RR
 2051  2055 TS
 2051  2056 TS
 2051  2057 TS
 2051  2058 TS
 2051  2059 TS
 2051  2060 TS
 2051  2061 TS
 2051  2063 TS
 2051  2067 TS
 2051  2068 TS
 2051  2069 TS
 2051  2070 TS
 2051  2072 TS
 2051  2073 TS
 2051  2074 TS
 2051  2075 TS
 2051  2077 TS
 2051  2078 TS
 2051  2080 TS
 2051  2356 RR
 2051  2386 TS
 2051  2387 TS

编辑: 我运行了以下简单的pthread程序,并像上面那样进行了测试。 不幸的是,chrt命令只能改变主线程的类别。 请参见下文。
$ ps -Lo pid,tid,class 3552
  PID   TID CLS
 3552  3552 TS
 3552  3553 TS
 3552  3554 TS
 3552  3555 TS
 3552  3556 TS
 3552  3557 TS

$ sudo chrt --rr -p 30 3552
 ...
$ ps -Lo pid,tid,class 3552
  PID   TID CLS
 3552  3552 RR
 3552  3553 TS
 3552  3554 TS
 3552  3555 TS
 3552  3556 TS
 3552  3557 TS

---- 程序 ----

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS     5

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   long k = 1;
   long a[10000];
   int i = 1;
  long b[10000];

   for (k = 0; k < 400000000; k++) {
        if (i == 9999) {
       i = 1;   
    } 
    a[i] = ((k + i) * (k - i))/2;
    a[i] = k/2;
        b[i] = i * 20;
    b[i] = a[i] - b[i];
        i++;
    int j = 0;
    for (j = 0; j < i; j++) {
        k = j - i;  
    } 
     } 
    
   pthread_exit(NULL);
   
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

如果想要了解如何在代码中进行而不是在命令行中执行此操作的5个详细演示,请查看我在这里的答案。更具体地说,请在我的**sleep_nanosleep_minimum_time_interval.c**测试文件的set_scheduler()函数内查看"Demo 1"到"Demo 5"。 - Gabriel Staples
2个回答

使用chrt命令和chrt --rr <1-99之间的优先级> <命令> 示例:
# Note: `sudo` is not required if you are root
chrt --rr 99 ls

# use `sudo` otherwise
sudo chrt --rr 99 ls

请注意,设置SCHED_RR需要root权限,因此您必须是root用户或使用sudo运行它。
您还可以使用chrt为正在运行的进程提供实时优先级: chrt -p --rr <1-99之间的优先级> <pid> 对于其他调度类别,相同的命令也适用,只是参数不同而已。
Scheduling policies:
  -b | --batch         set policy to SCHED_BATCH
  -f | --fifo          set policy to SCHED_FIFO
  -i | --idle          set policy to SCHED_IDLE
  -o | --other         set policy to SCHED_OTHER
  -r | --rr            set policy to SCHED_RR (default)

编辑:

在Firefox的情况下,必须具体到Firefox。在我自己编写的多线程应用程序中,所有线程都保持RR类。正如您的输出所示,两个线程都有RR类,所以不仅仅是父线程。

编辑2:

尝试使用chrt启动进程,而不是重新调度现有的pid。看起来,如果您重新调度,只有第一个线程会得到RR类。然而,如果您使用chrt启动它,每个线程都会得到它。


谢谢 @Egil。顺便问一下,默认的调度类是 TS 对吧。你可以在 ps 命令的输出中看到。 - samarasa
是的...它是这样工作的。不知何故,如果我们提供pid,它就无法正常工作。 - samarasa
有太少的-r(只使用了两次),我建议改用-rrrrrrrrr代替 ;-P - poige
在我的设备上运行它不需要root权限... - enigmaticPhysicist
@samarasa:也许你需要使用-a选项。根据手册: -a, --all-tasks 设置或检索给定PID的所有任务(线程)的调度属性。 - Narcolessico
运行chrt --max命令可以查看每个调度器类型可以指定的优先级范围列表。RR显示为1-99:SCHED_RR min/max priority : 1/99。问题是:哪个是最高优先级?是1还是99 - Gabriel Staples
我进行了大量的研究和阅读,在多个地方找到了相关信息,但我想回报一下:对于“SCHED_RR”轮转调度策略,99是最高优先级,而1是最低优先级。这里是众多来源之一,其中明确说明:“(SCHED_FIFO, SCHED_RR) 的 sched_priority 值范围为 1(低)到 99(高)”。 - Gabriel Staples
对于任何认为这是显而易见的人来说,事实并非如此。许多优先级系统都是反向的。例如,针对ARM核心微控制器的NVIC(嵌套向量中断控制器)就是反向的,其中0是_最高优先级_,而255是_最低优先级_。请参见此处。因此,关于Linux SCHED_RR循环调度器的优先级级别从199,我不得不询问。 - Gabriel Staples

只需在线程代码中添加此代码:

pthread_t this_thread = pthread_self();
struct sched_param params;
params.sched_priority = sched_get_priority_max(SCHED_RR);
pthread_setschedparam(this_thread, SCHED_RR, &params);

这将为运行此代码的任何线程提供最大的 SCHED_RR(循环调度实时调度程序)优先级为99
参见:
  1. 每个调度程序策略的说明,包括循环调度软实时调度程序 SCHED_RR: https://man7.org/linux/man-pages/man7/sched.7.html
  2. 提到 SCHED_RR 调度程序的最小和最大优先级分别为 199https://man7.org/linux/man-pages/man2/sched_get_priority_min.2.html
  3. https://man7.org/linux/man-pages/man3/pthread_setschedparam.3.html

1你可能实际上希望将线程的优先级设置为最低的1,而不是最高优先级的99,以确保不会阻塞需要高优先级的线程,比如网络堆栈。我不能百分之百确定,但我认为将线程的优先级设置为99可能会阻塞网络堆栈并导致奇怪的错误。使用SCHED_RR策略是必要的,以获得更好的时间分辨率(约5微秒的睡眠分辨率与55微秒的睡眠分辨率相比),当使用clock_nanosleep()等调用时,但在此策略中使用最高优先级是不必要的。 - Gabriel Staples
这是另一个很好的资源,可以阅读了解Linux软实时调度策略和优先级:Dr. Dobb's: Soft Real-Time Programming with Linux - Gabriel Staples
1顺便说一句,感谢你在这里的回答。它帮助我找到了自己的答案:请参见我的回答,并且我在编写我的**sleep_nanosleep_minimum_time_interval.c**测试文件中的set_scheduler()函数内的"Demo 1"到"Demo 5"中引用了它。 - Gabriel Staples