概念

Linux系统中常用的几种调度类为SCHED_NORMAL、SCHED_FIFO、SCHED_RR

  • SCHED_NORMAL:用于普通线程的调度类
  • SCHED_FIFO和SCHED_RR是用于实时线程的调度类,优先级高于SCHED_NORMAL。

内核中区分普通线程与实时线程是根据线程的优先级,实时线程拥有实时优先级(real-time priority),默认取值为0~99,数值越高优先级越高

普通线程只具有nice值,nice值映射到用户层的取值范围为-20~+19,数值越高优先级越低,默认初始值为0 ,子线程会继承父线程的优先级。

标准函数

  1. #include <pthread.h>
  2. pthread_setschedparam(pthread_t thread, int policy,
  3. const struct sched_param *param);
  4. pthread_getschedparam(pthread_t thread, int *policy,
  5. struct sched_param *param);
  6. Compile and link with -pthread.
  • 描述:

    • pthread_setschedparam函数用于设置调度策略policy和线程参数(也就是优先级)
    • pthread_getschedparam函数用户获取调度策略policy和线程参数(也就是优先级)
  • 参数说明:

    • policy参数:线程新的调度策略,policy的描述可查看sched_setscheduler(2)
    1. // /usr/include/bits/sched.h
    2. #define SCHED_OTHER 0
    3. #define SCHED_FIFO 1
    4. #define SCHED_RR 2
    • param参数:指定新的调度策略的参数,每一种调度策略的优先级允许设置的范围可查看sched_setscheduler(2)
    1. struct sched_param {
    2. int sched_priority; /* Scheduling priority */
    3. };
  • 返回值:成功返回0,失败返回非0值。常见的错误值

    1. // /usr/include/asm-generic/errno-base.h
    2. #define EPERM 1 /* Operation not permitted */
    3. #define ESRCH 3 /* No such process */
    4. #define EINVAL 22 /* Invalid argument */
    • ESRCH: 线程ID未发现
    • EINVAL: policy不合法,或者param不合法
    • EPERM: 没有权限,policy为SCHED_FIFO、SCHED_RR时,需要root权限

标准示例

示例演示了使用pthread_setschedparam() 和 pthread_getschedparam()和其它一些与实施调度相关的一些函数。

  • main thread设置为SCHED_FIFO调度策略,优先级设置为10,并且初始化一个线程属性对象:调度策略SCHED_RR,优先级20。
  • 接着程序设置线程的继承调度器属性为PTHREAD_EXPLICIT_SCHED -- 创建的线程属性应该为线程属性对象的调度器属性。
  • 接着使用线程属性对象创建一个线程,然后显示线程的调度策略和优先级。

源码:standerd_examp.c.c

  1. /* pthreads_sched_test.c */
  2. #include <pthread.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #define handle_error_en(en, msg) \
  8. do { \
  9. errno = en; \
  10. perror(msg); \
  11. exit(EXIT_FAILURE); \
  12. } while (0)
  13. static void
  14. usage(char *prog_name, char *msg)
  15. {
  16. if (msg != NULL)
  17. fputs(msg, stderr);
  18. fprintf(stderr, "Usage: %s [options]\n", prog_name);
  19. fprintf(stderr, "Options are:\n");
  20. #define fpe(msg) fprintf(stderr, "\t%s", msg); /* Shorter */
  21. fpe("-a<policy><prio> Set scheduling policy and priority in\n");
  22. fpe(" thread attributes object\n");
  23. fpe(" <policy> can be\n");
  24. fpe(" f SCHED_FIFO\n");
  25. fpe(" r SCHED_RR\n");
  26. fpe(" o SCHED_OTHER\n");
  27. fpe("-A Use default thread attributes object\n");
  28. fpe("-i {e|s} Set inherit scheduler attribute to\n");
  29. fpe(" 'explicit' or 'inherit'\n");
  30. fpe("-m<policy><prio> Set scheduling policy and priority on\n");
  31. fpe(" main thread before pthread_create() call\n");
  32. exit(EXIT_FAILURE);
  33. }
  34. static int
  35. get_policy(char p, int *policy)
  36. {
  37. switch (p) {
  38. case 'f':
  39. *policy = SCHED_FIFO;
  40. return 1;
  41. case 'r':
  42. *policy = SCHED_RR;
  43. return 1;
  44. case 'o':
  45. *policy = SCHED_OTHER;
  46. return 1;
  47. default:
  48. return 0;
  49. }
  50. }
  51. static void
  52. display_sched_attr(int policy, struct sched_param *param)
  53. {
  54. printf(" policy=%s, priority=%d\n",
  55. (policy == SCHED_FIFO) ? "SCHED_FIFO" :
  56. (policy == SCHED_RR) ? "SCHED_RR" :
  57. (policy == SCHED_OTHER) ? "SCHED_OTHER" :
  58. "???",
  59. param->sched_priority);
  60. }
  61. static void
  62. display_thread_sched_attr(char *msg)
  63. {
  64. int policy, s;
  65. struct sched_param param;
  66. s = pthread_getschedparam(pthread_self(), &policy, &param);
  67. if (s != 0)
  68. handle_error_en(s, "pthread_getschedparam");
  69. printf("%s\n", msg);
  70. display_sched_attr(policy, &param);
  71. }
  72. static void *
  73. thread_start(void *arg)
  74. {
  75. display_thread_sched_attr("Scheduler attributes of new thread");
  76. return NULL;
  77. }
  78. int main(int argc, char *argv[])
  79. {
  80. int s, opt, inheritsched, use_null_attrib, policy;
  81. pthread_t thread;
  82. pthread_attr_t attr;
  83. pthread_attr_t *attrp;
  84. char *attr_sched_str, *main_sched_str, *inheritsched_str;
  85. struct sched_param param;
  86. /* Process command-line options */
  87. use_null_attrib = 0;
  88. attr_sched_str = NULL;
  89. main_sched_str = NULL;
  90. inheritsched_str = NULL;
  91. while ((opt = getopt(argc, argv, "a:Ai:m:")) != -1) {
  92. switch (opt) {
  93. case 'a':
  94. attr_sched_str = optarg;
  95. break;
  96. case 'A':
  97. use_null_attrib = 1;
  98. break;
  99. case 'i':
  100. inheritsched_str = optarg;
  101. break;
  102. case 'm':
  103. main_sched_str = optarg;
  104. break;
  105. default:
  106. usage(argv[0], "Unrecognized option\n");
  107. }
  108. }
  109. if (use_null_attrib && (inheritsched_str != NULL || attr_sched_str != NULL))
  110. usage(argv[0], "Can't specify -A with -i or -a\n");
  111. /* Optionally set scheduling attributes of main thread,
  112. and display the attributes */
  113. if (main_sched_str != NULL) {
  114. if (!get_policy(main_sched_str[0], &policy))
  115. usage(argv[0], "Bad policy for main thread (-s)\n");
  116. param.sched_priority = strtol(&main_sched_str[1], NULL, 0);
  117. s = pthread_setschedparam(pthread_self(), policy, &param);
  118. if (s != 0)
  119. handle_error_en(s, "pthread_setschedparam");
  120. }
  121. display_thread_sched_attr("Scheduler settings of main thread");
  122. printf("\n");
  123. /* Initialize thread attributes object according to options */
  124. attrp = NULL;
  125. if (!use_null_attrib) {
  126. s = pthread_attr_init(&attr);
  127. if (s != 0)
  128. handle_error_en(s, "pthread_attr_init");
  129. attrp = &attr;
  130. }
  131. if (inheritsched_str != NULL) {
  132. if (inheritsched_str[0] == 'e')
  133. inheritsched = PTHREAD_EXPLICIT_SCHED;
  134. else if (inheritsched_str[0] == 'i')
  135. inheritsched = PTHREAD_INHERIT_SCHED;
  136. else
  137. usage(argv[0], "Value for -i must be 'e' or 'i'\n");
  138. s = pthread_attr_setinheritsched(&attr, inheritsched);
  139. if (s != 0)
  140. handle_error_en(s, "pthread_attr_setinheritsched");
  141. }
  142. if (attr_sched_str != NULL) {
  143. if (!get_policy(attr_sched_str[0], &policy))
  144. usage(argv[0],
  145. "Bad policy for 'attr' (-a)\n");
  146. param.sched_priority = strtol(&attr_sched_str[1], NULL, 0);
  147. s = pthread_attr_setschedpolicy(&attr, policy);
  148. if (s != 0)
  149. handle_error_en(s, "pthread_attr_setschedpolicy");
  150. s = pthread_attr_setschedparam(&attr, &param);
  151. if (s != 0)
  152. handle_error_en(s, "pthread_attr_setschedparam");
  153. }
  154. /* If we initialized a thread attributes object, display
  155. the scheduling attributes that were set in the object */
  156. if (attrp != NULL) {
  157. s = pthread_attr_getschedparam(&attr, &param);
  158. if (s != 0)
  159. handle_error_en(s, "pthread_attr_getschedparam");
  160. s = pthread_attr_getschedpolicy(&attr, &policy);
  161. if (s != 0)
  162. handle_error_en(s, "pthread_attr_getschedpolicy");
  163. printf("Scheduler settings in 'attr'\n");
  164. display_sched_attr(policy, &param);
  165. s = pthread_attr_getinheritsched(&attr, &inheritsched);
  166. printf(" inheritsched is %s\n",
  167. (inheritsched == PTHREAD_INHERIT_SCHED) ? "INHERIT" :
  168. (inheritsched == PTHREAD_EXPLICIT_SCHED) ? "EXPLICIT" :
  169. "???");
  170. printf("\n");
  171. }
  172. /* Create a thread that will display its scheduling attributes */
  173. s = pthread_create(&thread, attrp, &thread_start, NULL);
  174. if (s != 0)
  175. handle_error_en(s, "pthread_create");
  176. /* Destroy unneeded thread attributes object */
  177. s = pthread_attr_destroy(&attr);
  178. if (s != 0)
  179. handle_error_en(s, "pthread_attr_destroy");
  180. s = pthread_join(thread, NULL);
  181. if (s != 0)
  182. handle_error_en(s, "pthread_join");
  183. exit(EXIT_SUCCESS);
  184. }

测试:

  1. # 默认启动的线程为调度policy为SCHED_OTHER, 默认的调度优先级为0
  2. root@ubuntu:/home/grace# ./a.out
  3. Scheduler settings of main thread
  4. policy=SCHED_OTHER, priority=0
  5. # 没有设置attribute
  6. Scheduler settings in 'attr'
  7. policy=SCHED_OTHER, priority=0
  8. inheritsched is INHERIT
  9. # 新创建线程优先级和main一致
  10. Scheduler attributes of new thread
  11. policy=SCHED_OTHER, priority=0
  1. # 设置main线程调度策略为SCHED_FIFO, 调度优先级为10
  2. # 设置thread attributes object的调度策略为SCHED_RR, 优先级为20
  3. # 设置inherit scheduler attribute为PTHREAD_EXPLICIT_SCHED
  4. # 测试结果为新创建的线程的调度策略和优先级为attribute object设置的值
  5. root@ubuntu:/home/grace# ./a.out -mf10 -ar20 -i e
  6. Scheduler settings of main thread
  7. policy=SCHED_FIFO, priority=10
  8. Scheduler settings in 'attr'
  9. policy=SCHED_RR, priority=20
  10. inheritsched is EXPLICIT
  11. Scheduler attributes of new thread
  12. policy=SCHED_RR, priority=20
  1. # 设置main线程调度策略为SCHED_FIFO, 调度优先级为10
  2. # 设置thread attributes object的调度策略为SCHED_RR, 优先级为20
  3. # 设置inherit scheduler attribute为PTHREAD_INHERIT_SCHED,
  4. # 测试结果为新创建的线程会忽略attribute object设置的值, 属性值直接从父线程继承
  5. root@ubuntu:/home/grace# ./a.out -mf10 -ar20 -i i
  6. Scheduler settings of main thread
  7. policy=SCHED_FIFO, priority=10
  8. Scheduler settings in 'attr'
  9. policy=SCHED_RR, priority=20
  10. inheritsched is INHERIT
  11. Scheduler attributes of new thread
  12. policy=SCHED_FIFO, priority=10

相关工具

ps

可以查看线程的调度优先级和nice值。

测试代码:ps.c

  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #define handle_error_en(en, msg) \
  7. do { \
  8. errno = en; \
  9. perror(msg); \
  10. exit(EXIT_FAILURE); \
  11. } while (0)
  12. static void *thread0_func(void *arg)
  13. {
  14. int policy;
  15. int s;
  16. struct sched_param param;
  17. policy = SCHED_FIFO;
  18. param.sched_priority = 60;
  19. s = pthread_setschedparam(pthread_self(), policy, &param);
  20. if (s != 0)
  21. handle_error_en(s, "pthread_setschedparam");
  22. while (1) {
  23. sleep(1);
  24. }
  25. return NULL;
  26. }
  27. static void *thread1_func(void *arg)
  28. {
  29. int policy;
  30. int s;
  31. struct sched_param param;
  32. policy = SCHED_RR;
  33. param.sched_priority = 20;
  34. s = pthread_setschedparam(pthread_self(), policy, &param);
  35. if (s != 0)
  36. handle_error_en(s, "pthread_setschedparam");
  37. while (1) {
  38. sleep(1);
  39. }
  40. return NULL;
  41. }
  42. static void *thread2_func(void *arg)
  43. {
  44. int policy;
  45. int s;
  46. struct sched_param param;
  47. policy = SCHED_OTHER;
  48. param.sched_priority = 0; // 设置调度策略为SCHED_OTHER时, 优先级必须设置为0
  49. s = pthread_setschedparam(pthread_self(), policy, &param);
  50. if (s != 0) {
  51. handle_error_en(s, "pthread_setschedparam");
  52. }
  53. while (1) {
  54. sleep(1);
  55. }
  56. return NULL;
  57. }
  58. int main(int argc, char *argv[])
  59. {
  60. int s;
  61. pthread_t thread0, thread1, thread2;
  62. s = pthread_create(&thread0, NULL, &thread0_func, NULL);
  63. if (s != 0)
  64. handle_error_en(s, "pthread_create");
  65. s = pthread_create(&thread1, NULL, &thread1_func, NULL);
  66. if (s != 0)
  67. handle_error_en(s, "pthread_create");
  68. s = pthread_create(&thread2, NULL, &thread2_func, NULL);
  69. if (s != 0)
  70. handle_error_en(s, "pthread_create");
  71. s = pthread_join(thread0, NULL);
  72. if (s != 0)
  73. handle_error_en(s, "pthread_join");
  74. s = pthread_join(thread1, NULL);
  75. if (s != 0)
  76. handle_error_en(s, "pthread_join");
  77. s = pthread_join(thread2, NULL);
  78. if (s != 0)
  79. handle_error_en(s, "pthread_join");
  80. exit(EXIT_SUCCESS);
  81. }

功能:在主线程中会创建三个线程

  • 第一个线程的调度策略为SCHED_FIFO, 优先级为60
  • 第二个线程的调度策略为SCHED_RR, 优先级为20
  • 第三个线程德调度策略为SCHED_OTHER, 优先级只能配置为0
  1. $ ps -Telf
  2. F S UID PID SPID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
  3. 4 S root 2139 2139 2138 0 80 0 - 6840 - 20:41 pts/6 00:00:00 ./a.out # 线程调度策略为SCHED_OTHER, nice值为0
  4. 5 S root 2139 2140 2138 0 -1 - - 6840 - 20:41 pts/6 00:00:00 ./a.out # real-time调度策略
  5. 5 S root 2139 2141 2138 0 39 - - 6840 - 20:41 pts/6 00:00:00 ./a.out # real-time调度策略
  6. 5 S root 2139 2142 2138 0 80 0 - 6840 - 20:41 pts/6 00:00:00 ./a.out

部分字段含义:

  • PRI: priority of the process. Higher number means lower priority.
  • NI: nice value. This ranges from 19 (nicest) to -20 (not nice to others), see nice(1). (alias nice).

chrt工具

用来查看或改变线程的real-time调度属性


  1. F S UID PID SPID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
  2. 4 S root 2139 2139 2138 0 80 0 - 6840 - 20:41 pts/6 00:00:00 ./a.out # 线程调度策略为SCHED_OTHER, nice值为0
  3. 5 S root 2139 2140 2138 0 -1 - - 6840 - 20:41 pts/6 00:00:00 ./a.out # real-time调度策略
  4. 5 S root 2139 2141 2138 0 39 - - 6840 - 20:41 pts/6 00:00:00 ./a.out # real-time调度策略
  5. 5 S root 2139 2142 2138 0 80 0 - 6840 - 20:41 pts/6 00:00:00 ./a.out
  6. $ chrt -p 2139
  7. pid 2139's current scheduling policy: SCHED_OTHER
  8. pid 2139's current scheduling priority: 0
  9. $ chrt -p 2140
  10. pid 2140's current scheduling policy: SCHED_FIFO
  11. pid 2140's current scheduling priority: 60
  12. $ chrt -p 2141
  13. pid 2141's current scheduling policy: SCHED_RR
  14. pid 2141's current scheduling priority: 20
  15. $ chrt -p 2142
  16. pid 2142's current scheduling policy: SCHED_OTHER
  17. pid 2142's current scheduling priority: 0

chrt工具看到的SCHED_OTHER类型的进程的优先级都为0,可以通过cat /proc/tast-num/sched查看:

  1. SessionLeader (734, #threads: 1)
  2. -------------------------------------------------------------------
  3. policy : 0 # 调度策略
  4. prio : 120 # 优先级
  5. clock-delta : 100

SCHED_SETSCHEDULER(2)

参考:https://zhuanlan.zhihu.com/p/618044514?utm_id=0

  1. #include <sched.h>
  2. int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
  3. int sched_getscheduler(pid_t pid);
  4. struct sched_param {
  5. ...
  6. int sched_priority;
  7. ...
  8. };

sched_setscheduler函数的作用是为pid指定的线程设置调度策略和优先级。如果pid为0,则会设置调用该函数的线程的策略和优先级。

sched_getscheduler函数作用是查询pid指定的线程的调度策略和优先级。如果pid为0,则会查询调用该函数的线程的策略和优先级。

Linux支持的调度策略分为两类:

  • normal类型:

    • SCHED_OTHER the standard round-robin time-sharing policy; # 循环分时调度策略
    • SCHED_IDLE for running very low priority background jobs. # 低优先级线程作为背景线程运行
  • real-time类型
    • SCHED_FIFO a first-in, first-out policy; # 先进先出调度策略
    • SCHED_RR a round-robin policy. # 轮转调度

Scheduling policies

  • 调度器是内核的一部分,用来决定哪个就绪态线程获取CPU执行。每一个线程有一个关联的调度策略和一个static调度优先级sched_priority,这些参数可以通过sched_setscheduler()函数设置。内核中的调度器根据调度策略和所有处理器的static priority决定调度哪个线程。
  • 使用normal调度策略(SCHED_OTHER, SCHED_IDLE, SCHED_BATCH)的线程,sched_priority参数没有使用,必须设置为0。
  • 使用real-time调度策略(SCHED_FIFO, SCHED_RR)有一个sched_priority,范围1 (low) 到 99 (high)。(real-time类型线程总是高于normal类型线程)。可以使用sched_get_priority_min()和sched_get_priority_max()函数查看每个调度策略对应的优先级范围。
  • 调度器根据sched_priority值保存一个可运行线程列表,然后调度器选择最高的static priority线程列表,选择列表开头的线程运行。
  • 同样的static priority的线程,调度器根据调度算法决定哪个运行。
  • 线程的调度策略决定线程将插入到具有同等优先级的线程列表中的位置。
  • 所有的调度都是抢占式的,如果具有高静态优先级的线程准备运行,则当前正在运行的线程将被抢占并返回到其静态优先级的等待列表中。调度策略仅在具有同等静态优先级的可运行线程列表中确定排序。

SCHED_FIFO: First in-first out scheduling

  • SCHED_FIFO只能使用static priorities大于0的值。这表示,当一个调度策略为SCHED_FIFO的线程变成运行态时,总是优先于当前正在运行的SCHED_OTHER, SCHED_BATCH, or SCHED_IDLE策略的线程。
  • SCHED_FIFO是一个简单的调度算法,没有切分时间片。
  • 调度策略为SCHED_FIFO的线程遵循下面的规则:
    • 一个低优先级SCHED_FIFO调度的线程被更高优先级的线程抢占后,会放在同等优先级列表的头部,等待所有更高优先级的线程执行完毕后,会恢复执行。
    • 当一个阻塞的SCHED_FIFO线程变成就绪态时,会放在同等优先级列表的尾部。
    • 可以使用sched_setscheduler(2)、sched_setparam(2)、sched_setattr(2)、pthread_setschedparam(3) 或 pthread_setschedprio(3)函数设置正在运行的SCHED_FIFO调度线程的优先级,则对线程在列表中的位置影响却决于线程优先级的更改方向。
      • 如果线程的优先级提高,将其放在新的线程列表的尾部。
      • 如果线程的优先级不变,则其在列表中的位置不变。
      • 如果线程的优先级降低,则将其放在新优先级列表的前面。
    • 一个线程调用sched_yield()函数将放到列表的尾部。
    • 一个SCHED_FIFO线程会一直运行,除非被I/O请求阻塞,或者被更高优先级线程抢占,或者调用sched_yield()函数。

SCHED_RR: Round-robin scheduling

  • SCHED_RR调度策略是SCHED_FIFO策略的增强版本。
  • 适用于SCHED_FIFO的策略也适用于SCHED_RR,除了每一个线程仅被运行执行一个最大的时间片。
  • 如果SCHED_RR线程运行时间已经大于等于了时间片,它会被放在同等优先级列表的尾部。
  • 一个SCHED_RR线程被更高优先级的线程抢占后,恢复执行时使用未消耗完的时间片。
  • 时间片可以使用sched_rr_get_interval()函数查询。

SCHED_OTHER: Default Linux time-sharing scheduling

  • SCHED_OTHER调度策略仅能使用static priority为0(real-time的优先级始终高于normal)。
  • SCHED_OTHER是标准的时间片轮转调度,适用于不需要特殊实时机制的所有线程。
  • 要运行的线程是从static priority为0列表中选择的,该列表基于一个动态优先级。
  • 动态优先级基于nice值,可以通过nice()或者setpriority()设置。
  • 当线程准备运行但被调度器拒绝运行时,nice值也会增加。
  • nice值是一个属性,它会影响SCHED_OTHER和SCHED_BATCH(见下文)进程的调度。nice 值可以使用 nice(2)、setpriority(2) 或 sched_setattr(2) 进行修改。
  • Linux上,nice值的范围是-20(高优先级)到+19(低优先级)。

SCHED_IDLE: Scheduling very low priority jobs

  • SCHED_IDLE线程的static priority值为0。线程的nice值对此调度策略没有影响。
  • SCHED_IDLE调度策略适用于优先级非常低的线程。

Resetting scheduling policy for child processes

  • 每一个线程有一个reset-on-fork调度标志。设置此标志后,fork()创建的子进程不会继承特权调度策略,可以通过下面的方式设置此标志:

    • 当调用sched_setscheduler()函数时,将标志SCHED_RESET_ON_FORK放入策略参数中。
    • 调用 sched_setattr(2) 时,在 attr.sched_flags 中指定 SCHED_FLAG_RESET_ON_FORK 标志。
  • 当SCHED_RESET_ON_FORK标志设置后,创建的子线程将遵循下面的规则:
    • 如果父线程调度策略为SCHED_FIFO或者SCHED_RR,子线程将恢复为SCHED_OTHER;
    • 如果父线程有一个负的nice值,子线程的nice值将变为0;
    • 这个标志将在fork()函数创建子线程后失效,也就是子线程不继承这个标志;
    • 这个标志可以通过sched_getscheduler()函数查询。

Privileges and resource limits

  • 在Linux 2.6.12版本后,RLIMIT_RTPRIO限制了SCHED_RR和SCHED_FIFO调度策略的非特权程序的static priority上限。更改调度策略和优先级遵守下面的规则:

    • 如果一个非特权程序有非0的RLIMIT_RTPRIO软件限制,它可以改变它的调度策略和优先级。但优先级不能设置高于它当前的优先级的最大值和RLIMIT_RTPRIO软限制。
    • 如果RLIMIT_RTPRIO为0,则唯一允许的更改是降低优先级或切换到非real-time调度策略。
  • 可以使用RLIMIT_RTTIME资源限制来设置实时进程可能消耗的 CPU 时间的上限,详见getrlimit(2)
  • 从 Linux 2.6.25 开始,Linux 还提供了两个 /proc 文件,可用于保留一定数量的 CPU 时间供非real-time进程使用。以这种方式保留 CPU 时间允许将一些 CPU 时间分配给(例如)可用于终止失控进程的根 shell。这两个文件都以微秒为单位指定时间值:
    • /proc/sys/kernel/sched_rt_period_us: 指定相当于 100% CPU 带宽的调度周期。此文件中的值范围为 1 到 INT_MAX,工作范围为 1 微秒到 35 分钟左右。此文件中的默认值为 1,000,000(1 秒)。
    • /proc/sys/kernel/sched_rt_runtime_us: 此文件中的值指定系统上所有实时进程可以使用多少“周期”时间。此文件中的值的范围可以从 -1 到 INT_MAX-1。指定 -1 可使运行时间与周期相同;也就是说,没有为非实时进程留出 CPU 时间(这是 Linux 2.6.25 之前的行为)。此文件中的默认值为 950,000(0.95 秒),这意味着 5% 的 CPU 时间保留给不在实时调度策略下运行的进程。

测试代码

sched_test.c

  1. #include <sched.h>
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. int main(int argc,char *argv[])
  6. {
  7. struct sched_param param;
  8. int minpri, maxpri, count;
  9. // 获取SCHED_FIFO调度策略可配置的最大优先级
  10. maxpri = sched_get_priority_max(SCHED_FIFO);
  11. if(maxpri == -1) {
  12. perror("sched_get_priority_max() failed");
  13. return -1;
  14. }
  15. printf("max priority of SCHED_FIFO is %d\n", maxpri);
  16. minpri = sched_get_priority_min(SCHED_FIFO);
  17. if(minpri == -1) {
  18. perror("sched_get_priority_min() failed");
  19. return -1;
  20. }
  21. printf("min priority of SCHED_FIFO is %d\n", minpri);
  22. #if 0
  23. param.sched_priority = maxpri;
  24. if (sched_setscheduler(getpid(), SCHED_FIFO, &param) == -1) {
  25. perror("sched_setscheduler() failed");
  26. return -1;
  27. }
  28. #endif
  29. fork();
  30. fork();
  31. while(1) {
  32. count++;
  33. }
  34. return 0;
  35. }

功能:设置进程的调度策略为SCHED_FIFO, 并且优先级设置为最大,创建的子进程也会继承父进程的策略和优先级。

  1. F S UID PID SPID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
  2. 4 R root 19435 19435 19434 99 -40 - - 693 - 22:07 pts/5 00:00:07 ./a.out
  3. 1 R root 19436 19436 19435 99 -40 - - 693 - 22:07 pts/5 00:00:07 ./a.out
  4. 1 R root 19437 19437 19435 99 -40 - - 693 - 22:07 pts/5 00:00:07 ./a.out
  5. 1 R root 19438 19438 19436 99 -40 - - 693 - 22:07 pts/5 00:00:07 ./a.out
  6. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 19435
  7. pid 19435's current scheduling policy: SCHED_FIFO
  8. pid 19435's current scheduling priority: 99
  9. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 19436
  10. pid 19436's current scheduling policy: SCHED_FIFO
  11. pid 19436's current scheduling priority: 99
  12. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 19437
  13. pid 19437's current scheduling policy: SCHED_FIFO
  14. pid 19437's current scheduling priority: 99
  15. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 19438
  16. pid 19438's current scheduling policy: SCHED_FIFO
  17. pid 19438's current scheduling priority: 99

如果把#if 1改为#if 0, 则默认创建的是SCHED_OTHER类型进程

  1. F S UID PID SPID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
  2. 0 R grace 21187 17702 99 80 0 - 694 - 22:13 pts/0 00:00:02 ./a.out
  3. 1 R grace 21189 21187 99 80 0 - 694 - 22:13 pts/0 00:00:02 ./a.out
  4. 1 R grace 21190 21187 99 80 0 - 694 - 22:13 pts/0 00:00:02 ./a.out
  5. 1 R grace 21191 21189 99 80 0 - 694 - 22:13 pts/0 00:00:02 ./a.out
  6. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 17702
  7. pid 17702's current scheduling policy: SCHED_OTHER
  8. pid 17702's current scheduling priority: 0
  9. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 21187
  10. pid 21187's current scheduling policy: SCHED_OTHER
  11. pid 21187's current scheduling priority: 0
  12. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 21189
  13. pid 21189's current scheduling policy: SCHED_OTHER
  14. pid 21189's current scheduling priority: 0
  15. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 21190
  16. pid 21190's current scheduling policy: SCHED_OTHER
  17. pid 21190's current scheduling priority: 0
  18. grace@LAPTOP-UNTITVOP:~/thread-policy$ chrt -p 21191
  19. pid 21191's current scheduling policy: SCHED_OTHER
  20. pid 21191's current scheduling priority: 0

Linux-线程优先级学习的更多相关文章

  1. Linux线程优先级

    转自:https://www.cnblogs.com/imapla/p/4234258.html Linux内核的三种调度策略: 1.SCHED_OTHER 分时调度策略 2.SCHED_FIFO   ...

  2. Linux线程互斥学习笔记--详细分析

    一.互斥锁 为啥要有互斥? 多个进程/线程执行的先后顺序不确定,何时切出CPU也不确定. 多个进程/线程访问变量的动作往往不是原子的. 1. 操作步骤 (1)创建锁 // 创建互斥锁mutex pth ...

  3. Linux 线程优先级

    http://www.cnblogs.com/imapla/p/4234258.html http://blog.csdn.net/lanseshenhua/article/details/55247 ...

  4. Linux 线程调度策略与线程优先级

    Linux内核的三种调度策略 SCHED_OTHER 分时调度策略. 它是默认的线程分时调度策略,所有的线程的优先级别都是0,线程的调度是通过分时来完成的.简单地说,如果系统使用这种调度策略,程序将无 ...

  5. Linux 系统编程 学习:10-线程:线程的属性

    Linux 系统编程 学习:10-线程:线程的属性 背景 上一讲我们介绍了线程的创建,回收与销毁:简单地提到了线程属性.这一讲我们就来具体看看,线程的属性. 概述 #include <pthre ...

  6. Linux线程学习(一)

    一.Linux进程与线程概述 进程与线程 为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间.不同的线程可以存取内存中的同一个变量.所以,程序中的所有线程都可 ...

  7. EPROCESS 进程/线程优先级 句柄表 GDT LDT 页表 《寒江独钓》内核学习笔记(2)

    在学习笔记(1)中,我们学习了IRP的数据结构的相关知识,接下来我们继续来学习内核中很重要的另一批数据结构: EPROCESS/KPROCESS/PEB.把它们放到一起是因为这三个数据结构及其外延和w ...

  8. Linux 系统编程 学习:09-线程:线程的创建、回收与取消

    Linux 系统编程 学习:09-线程:线程的创建.回收与取消 背景 我们在此之前完成了 有关进程的学习.从这一讲开始我们学习线程. 完全的开发可以参考:<多线程编程指南> 在Linux ...

  9. Linux 系统编程 学习:11-线程:线程同步

    Linux 系统编程 学习:11-线程:线程同步 背景 上一讲 我们介绍了线程的属性 有关设置.这一讲我们来看线程之间是如何同步的. 额外安装有关的man手册: sudo apt-get instal ...

  10. <<Windows via C/C++>>学习笔记 —— 线程优先级【转】

    转自:http://www.cnblogs.com/wz19860913/archive/2008/08/04/1259807.html 每个线程都有一个“优先级”,范围是0-31,0为最低优先级,3 ...

随机推荐

  1. (节流)js防止重复频繁点击或者点击过快方法

    1.方法一:用定时器定时,没跑完定时器,点击按钮无效 <script> var isClick = true; $("button").on("click&q ...

  2. flutter 移动应用程序中打开URL

    url_launcher: ^6.2.5   在Flutter中,url_launcher库是用于在移动应用程序中打开URL的常用工具.它允许你通过调用系统的浏览器或其他应用程序来打开指定的URL,比 ...

  3. 力扣1126(MySQL)-查询活跃业务(中等)

    题目: 事件表:Events 此表的主键是 (business_id, event_type). 表中的每一行记录了某种类型的事件在某些业务中多次发生的信息. 问题写一段 SQL 来查询所有活跃的业务 ...

  4. 力扣569(MySQL)-员工薪水中位数(困难)

    题目: 写一个SQL查询,找出每个公司的工资中位数,以任意顺序返回结果表.查询结果个数如下所示. 输出结果如下:  解题思路: 中位数:位于集合正中间的元素.当数据总书为奇数时,最中间的数就是中位数, ...

  5. 解析 RocketMQ 业务消息——“事务消息”

    简介: 本篇文章通过拆解 RocketMQ 事务消息的使用场景.基本原理.实现细节和实战使用,帮助大家更好的理解和使用 RocketMQ 的事务消息. 作者:合伯   引言:在分布式系统调用场景中存在 ...

  6. 基于英特尔® 优化分析包(OAP)的 Spark 性能优化方案

    ​简介: Spark SQL 作为 Spark 用来处理结构化数据的一个基本模块,已经成为多数企业构建大数据应用的重要选择.但是,在大规模连接(Join).聚合(Aggregate)等工作负载下,Sp ...

  7. [Go] 获得一个整数范围区间的随机数 (golang)

    示例:0,1 随机 package main import "fmt" import "math/rand" import "time" f ...

  8. 《最新出炉》系列入门篇-Python+Playwright自动化测试-42-强大的可视化追踪利器Trace Viewer

    1.简介 在我们日常执行自动化测试工作的过程中,经常会遇到一些偶发性的bug,但是因为bug是偶发性的,我们不一定每次执行都能复现,所以我们在测试执行的时候,追踪用例执行就变得非常重要了.playwr ...

  9. centos 7 开启 httpd 服务和 80 端口

    centos 7 开启 httpd 服务和 80 端口 yum install -y httpd systemctl start httpd firewall-cmd --add-service=ht ...

  10. idea在商店无法搜索到插件

    背景:我使用的版本是IDEA ultimate 2019.2 版本印象中,最初安装的时候,商店还是可以用的,突然有一天,就无法使用了.下边直入正题: 解决办法:1.首先浏览器登陆下:https://p ...