chrt.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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.4 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: "[-prfombi] [PRIO] [PID | PROG ARGS]"
  18. //usage:#define chrt_full_usage "\n\n"
  19. //usage: "Change scheduling priority and class for a process\n"
  20. //usage: "\n -p Operate on PID"
  21. //usage: "\n -r Set SCHED_RR class"
  22. //usage: "\n -f Set SCHED_FIFO class"
  23. //usage: "\n -o Set SCHED_OTHER class"
  24. //usage: "\n -b Set SCHED_BATCH class"
  25. //usage: "\n -i Set SCHED_IDLE class"
  26. //usage: "\n -m Show min/max priorities"
  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 struct {
  38. char name[sizeof("SCHED_OTHER")];
  39. } policies[] = {
  40. { "SCHED_OTHER" }, /* 0:SCHED_OTHER */
  41. { "SCHED_FIFO" }, /* 1:SCHED_FIFO */
  42. { "SCHED_RR" }, /* 2:SCHED_RR */
  43. { "SCHED_BATCH" }, /* 3:SCHED_BATCH */
  44. { "" }, /* 4:SCHED_ISO */
  45. { "SCHED_IDLE" }, /* 5:SCHED_IDLE */
  46. /* 6:SCHED_DEADLINE */
  47. };
  48. static void show_min_max(int pol)
  49. {
  50. const char *fmt = "%s min/max priority\t: %u/%u\n";
  51. int max, min;
  52. max = sched_get_priority_max(pol);
  53. min = sched_get_priority_min(pol);
  54. if ((max|min) < 0)
  55. fmt = "%s not supported\n";
  56. printf(fmt, policies[pol].name, min, max);
  57. }
  58. #define OPT_m (1<<0)
  59. #define OPT_p (1<<1)
  60. #define OPT_r (1<<2)
  61. #define OPT_f (1<<3)
  62. #define OPT_o (1<<4)
  63. #define OPT_b (1<<5)
  64. #define OPT_i (1<<6)
  65. int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  66. int chrt_main(int argc UNUSED_PARAM, char **argv)
  67. {
  68. pid_t pid = 0;
  69. unsigned opt;
  70. struct sched_param sp;
  71. char *pid_str;
  72. char *priority = priority; /* for compiler */
  73. const char *current_new;
  74. int policy = SCHED_RR;
  75. opt = getopt32(argv, "^"
  76. "+" "mprfobi"
  77. "\0"
  78. /* only one policy accepted: */
  79. "r--fobi:f--robi:o--rfbi:b--rfoi:i--rfob"
  80. );
  81. if (opt & OPT_m) { /* print min/max and exit */
  82. show_min_max(SCHED_OTHER);
  83. show_min_max(SCHED_FIFO);
  84. show_min_max(SCHED_RR);
  85. show_min_max(SCHED_BATCH);
  86. show_min_max(SCHED_IDLE);
  87. fflush_stdout_and_exit(EXIT_SUCCESS);
  88. }
  89. //if (opt & OPT_r)
  90. // policy = SCHED_RR; - default, already set
  91. if (opt & OPT_f)
  92. policy = SCHED_FIFO;
  93. if (opt & OPT_o)
  94. policy = SCHED_OTHER;
  95. if (opt & OPT_b)
  96. policy = SCHED_BATCH;
  97. if (opt & OPT_i)
  98. policy = SCHED_IDLE;
  99. argv += optind;
  100. if (!argv[0])
  101. bb_show_usage();
  102. if (opt & OPT_p) {
  103. pid_str = *argv++;
  104. if (*argv) { /* "-p <priority> <pid> [...]" */
  105. priority = pid_str;
  106. pid_str = *argv;
  107. }
  108. /* else "-p <pid>", and *argv == NULL */
  109. pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
  110. } else {
  111. priority = *argv++;
  112. if (!*argv)
  113. bb_show_usage();
  114. }
  115. current_new = "current\0new";
  116. if (opt & OPT_p) {
  117. int pol;
  118. print_rt_info:
  119. pol = sched_getscheduler(pid);
  120. if (pol < 0)
  121. bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', (int)pid);
  122. printf("pid %d's %s scheduling policy: %s\n",
  123. pid, current_new, policies[pol].name);
  124. if (sched_getparam(pid, &sp))
  125. bb_perror_msg_and_die("can't get pid %d's attributes", (int)pid);
  126. printf("pid %d's %s scheduling priority: %d\n",
  127. (int)pid, current_new, sp.sched_priority);
  128. if (!*argv) {
  129. /* Either it was just "-p <pid>",
  130. * or it was "-p <priority> <pid>" and we came here
  131. * for the second time (see goto below) */
  132. return EXIT_SUCCESS;
  133. }
  134. *argv = NULL;
  135. current_new += 8;
  136. }
  137. sp.sched_priority = xstrtou_range(priority, 0,
  138. sched_get_priority_min(policy), sched_get_priority_max(policy)
  139. );
  140. if (sched_setscheduler(pid, policy, &sp) < 0)
  141. bb_perror_msg_and_die("can't %cet pid %d's policy", 's', (int)pid);
  142. if (!argv[0]) /* "-p <priority> <pid> [...]" */
  143. goto print_rt_info;
  144. BB_EXECVP_or_die(argv);
  145. }