/apue/tlpi-book/procpri/demo_sched_fifo.c

https://gitlab.com/Gentio/my-pdf · C · 102 lines · 61 code · 21 blank · 20 comment · 15 complexity · ed628623a30c551ada02220c4973644d MD5 · raw file

  1. /*************************************************************************\
  2. * Copyright (C) Michael Kerrisk, 2015. *
  3. * *
  4. * This program is free software. You may use, modify, and redistribute it *
  5. * under the terms of the GNU General Public License as published by the *
  6. * Free Software Foundation, either version 3 or (at your option) any *
  7. * later version. This program is distributed without any warranty. See *
  8. * the file COPYING.gpl-v3 for details. *
  9. \*************************************************************************/
  10. /* Solution for Exercise 35-3 */
  11. #define _GNU_SOURCE
  12. #include <sched.h>
  13. #include <sys/resource.h>
  14. #include <sys/times.h>
  15. #include "tlpi_hdr.h"
  16. #define CSEC_STEP 25 /* CPU centiseconds between messages */
  17. static void
  18. useCPU(char *msg)
  19. {
  20. struct tms tms;
  21. int cpuCentisecs, prevStep, prevSec;
  22. prevStep = 0;
  23. prevSec = 0;
  24. for (;;) {
  25. if (times(&tms) == -1)
  26. errExit("times");
  27. cpuCentisecs = (tms.tms_utime + tms.tms_stime) * 100 /
  28. sysconf(_SC_CLK_TCK);
  29. if (cpuCentisecs >= prevStep + CSEC_STEP) {
  30. prevStep += CSEC_STEP;
  31. printf("%s (PID %ld) cpu=%0.2f\n", msg, (long) getpid(),
  32. cpuCentisecs / 100.0);
  33. }
  34. if (cpuCentisecs > 300) /* Terminate after 3 seconds */
  35. break;
  36. if (cpuCentisecs >= prevSec + 100) { /* Yield once/second */
  37. prevSec = cpuCentisecs;
  38. sched_yield();
  39. }
  40. }
  41. }
  42. int
  43. main(int argc, char *argv[])
  44. {
  45. struct rlimit rlim;
  46. struct sched_param sp;
  47. cpu_set_t set;
  48. setbuf(stdout, NULL); /* Disable buffering of stdout */
  49. /* Confine all processes to a single CPU, so that the processes
  50. won't run in parallel on multi-CPU systems. */
  51. CPU_ZERO(&set);
  52. CPU_SET(1, &set);
  53. if (sched_setaffinity(getpid(), sizeof(set), &set) == -1)
  54. errExit("sched_setaffinity");
  55. /* Establish a CPU time limit. This demonstrates how we can
  56. ensure that a runaway realtime process is terminated if we
  57. make a programming error. The resource limit is inherited
  58. by the child created using fork().
  59. An alternative technique would be to make an alarm() call in each
  60. process (since interval timers are not inherited across fork()). */
  61. rlim.rlim_cur = rlim.rlim_max = 50;
  62. if (setrlimit(RLIMIT_CPU, &rlim) == -1)
  63. errExit("setrlimit");
  64. /* Run the two processes in the lowest SCHED_FIFO priority */
  65. sp.sched_priority = sched_get_priority_min(SCHED_FIFO);
  66. if (sp.sched_priority == -1)
  67. errExit("sched_get_priority_min");
  68. if (sched_setscheduler(0, SCHED_FIFO, &sp) == -1)
  69. errExit("sched_setscheduler");
  70. switch (fork()) {
  71. case -1:
  72. errExit("fork");
  73. case 0:
  74. useCPU("child ");
  75. exit(EXIT_SUCCESS);
  76. default:
  77. useCPU("parent");
  78. exit(EXIT_SUCCESS);
  79. }
  80. }