chrt.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * chrt - manipulate real-time attributes of a process
  4. * Copyright (c) 2006-2007 Bernhard Reutner-Fischer
  5. *
  6. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  7. */
  8. //config:config CHRT
  9. //config: bool "chrt (4.7 kb)"
  10. //config: default y
  11. //config: help
  12. //config: Manipulate real-time attributes of a process.
  13. //config: This requires sched_{g,s}etparam support in your libc.
  14. //applet:IF_CHRT(APPLET_NOEXEC(chrt, chrt, BB_DIR_USR_BIN, BB_SUID_DROP, chrt))
  15. //kbuild:lib-$(CONFIG_CHRT) += chrt.o
  16. //usage:#define chrt_trivial_usage
  17. //usage: "-m | -p [PRIO] PID | [-rfobi] PRIO PROG [ARGS]"
  18. //usage:#define chrt_full_usage "\n\n"
  19. //usage: "Change scheduling priority and class for a process\n"
  20. //usage: "\n -m Show min/max priorities"
  21. //usage: "\n -p Operate on PID"
  22. //usage: "\n -r Set SCHED_RR class"
  23. //usage: "\n -f Set SCHED_FIFO class"
  24. //usage: "\n -o Set SCHED_OTHER class"
  25. //usage: "\n -b Set SCHED_BATCH class"
  26. //usage: "\n -i Set SCHED_IDLE class"
  27. //usage:
  28. //usage:#define chrt_example_usage
  29. //usage: "$ chrt -r 4 sleep 900; x=$!\n"
  30. //usage: "$ chrt -f -p 3 $x\n"
  31. //usage: "You need CAP_SYS_NICE privileges to set scheduling attributes of a process"
  32. #include <sched.h>
  33. #include "libbb.h"
  34. #ifndef SCHED_IDLE
  35. # define SCHED_IDLE 5
  36. #endif
  37. static const char *policy_name(int pol)
  38. {
  39. if (pol > 6)
  40. return utoa(pol);
  41. return nth_string(
  42. "OTHER" "\0" /* 0:SCHED_OTHER */
  43. "FIFO" "\0" /* 1:SCHED_FIFO */
  44. "RR" "\0" /* 2:SCHED_RR */
  45. "BATCH" "\0" /* 3:SCHED_BATCH */
  46. "ISO" "\0" /* 4:SCHED_ISO */
  47. "IDLE" "\0" /* 5:SCHED_IDLE */
  48. "DEADLINE", /* 6:SCHED_DEADLINE */
  49. pol
  50. );
  51. }
  52. static void show_min_max(int pol)
  53. {
  54. const char *fmt = "SCHED_%s min/max priority\t: %u/%u\n";
  55. int max, min;
  56. max = sched_get_priority_max(pol);
  57. min = sched_get_priority_min(pol);
  58. if ((max|min) < 0)
  59. fmt = "SCHED_%s not supported\n";
  60. printf(fmt, policy_name(pol), min, max);
  61. }
  62. #define OPT_m (1<<0)
  63. #define OPT_p (1<<1)
  64. #define OPT_r (1<<2)
  65. #define OPT_f (1<<3)
  66. #define OPT_o (1<<4)
  67. #define OPT_b (1<<5)
  68. #define OPT_i (1<<6)
  69. int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  70. int chrt_main(int argc UNUSED_PARAM, char **argv)
  71. {
  72. pid_t pid = 0;
  73. unsigned opt;
  74. struct sched_param sp;
  75. char *pid_str;
  76. char *priority = priority; /* for compiler */
  77. const char *current_new;
  78. int policy = SCHED_RR;
  79. opt = getopt32(argv, "^"
  80. "+" "mprfobi"
  81. "\0"
  82. /* only one policy accepted: */
  83. "r--fobi:f--robi:o--rfbi:b--rfoi:i--rfob"
  84. );
  85. if (opt & OPT_m) { /* print min/max and exit */
  86. show_min_max(SCHED_OTHER);
  87. show_min_max(SCHED_FIFO);
  88. show_min_max(SCHED_RR);
  89. show_min_max(SCHED_BATCH);
  90. show_min_max(SCHED_IDLE);
  91. fflush_stdout_and_exit(EXIT_SUCCESS);
  92. }
  93. //if (opt & OPT_r)
  94. // policy = SCHED_RR; - default, already set
  95. if (opt & OPT_f)
  96. policy = SCHED_FIFO;
  97. if (opt & OPT_o)
  98. policy = SCHED_OTHER;
  99. if (opt & OPT_b)
  100. policy = SCHED_BATCH;
  101. if (opt & OPT_i)
  102. policy = SCHED_IDLE;
  103. argv += optind;
  104. if (!argv[0])
  105. bb_show_usage();
  106. if (opt & OPT_p) {
  107. pid_str = *argv++;
  108. if (*argv) { /* "-p PRIO PID [...]" */
  109. priority = pid_str;
  110. pid_str = *argv;
  111. }
  112. /* else "-p PID", and *argv == NULL */
  113. pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
  114. } else {
  115. priority = *argv++;
  116. if (!*argv)
  117. bb_show_usage();
  118. }
  119. current_new = "current\0new";
  120. if (opt & OPT_p) {
  121. int pol;
  122. print_rt_info:
  123. pol = sched_getscheduler(pid);
  124. if (pol < 0)
  125. bb_perror_msg_and_die("can't %cet pid %u's policy", 'g', (int)pid);
  126. #ifdef SCHED_RESET_ON_FORK
  127. /* "Since Linux 2.6.32, the SCHED_RESET_ON_FORK flag
  128. * can be ORed in policy when calling sched_setscheduler().
  129. * As a result of including this flag, children created by
  130. * fork(2) do not inherit privileged scheduling policies"
  131. *
  132. * This bit is also returned by sched_getscheduler()!
  133. * (TODO: do we want to show it?)
  134. */
  135. pol &= ~SCHED_RESET_ON_FORK;
  136. #endif
  137. printf("pid %u's %s scheduling policy: SCHED_%s\n",
  138. pid, current_new, policy_name(pol)
  139. );
  140. if (sched_getparam(pid, &sp))
  141. bb_perror_msg_and_die("can't get pid %u's attributes", (int)pid);
  142. printf("pid %u's %s scheduling priority: %d\n",
  143. (int)pid, current_new, sp.sched_priority
  144. );
  145. if (!*argv) {
  146. /* Either it was just "-p PID",
  147. * or it was "-p PRIO PID" and we came here
  148. * for the second time (see goto below) */
  149. return EXIT_SUCCESS;
  150. }
  151. *argv = NULL;
  152. current_new += 8;
  153. }
  154. sp.sched_priority = xstrtou_range(priority, 0,
  155. sched_get_priority_min(policy), sched_get_priority_max(policy)
  156. );
  157. if (sched_setscheduler(pid, policy, &sp) < 0)
  158. bb_perror_msg_and_die("can't %cet pid %u's policy", 's', (int)pid);
  159. if (!argv[0]) /* "-p PRIO PID [...]" */
  160. goto print_rt_info;
  161. BB_EXECVP_or_die(argv);
  162. }