C460 Lecture notes -- Priorities in Unix

  • Jim Plank
  • CS560: Operating Systems
  • Directory: http://www.cs.utk.edu/~mbeck/classes/cs560/560/notes/Chap5
  • Lecture notes: http://www.cs.utk.edu/~mbeck/classes/cs560/560/notes/Chap5/spin.html

    IMPORTANT

    If you copy and execute the spin or spintest programs, make sure you don't have stray spin processes when you're done. Do a ps x and kill your strays.

    Also, note that the output below was on my old sunos machine. The ps calls look different for Solaris, but the relative numbers will be the same.


    Priorities in Unix

    Unix uses a priority-based scheduling scheme. Processes can define a ``nice'' value which goes from -20 to 19. When scheduling decisions need to be made, the operating system uses each process's nice value and other information (how long it is been waiting on the ready queue, etc) to calculate a priority number between zero and 127. The lower the number, the higher the priority. Processes can set and change their nice values using the nice() function and the setpriority() system calls. Regular user processes may only have nice values from 0 to 19. System processes (those owned by root) may have nice values from -20 to 19. Read the man page on nice for more info.

    The spin program

    Spin.c is a program that alternates spinning the CPU and writing the character 'a' to standard output:
    #include < stdio.h >
    
    main(argc, argv)
    int argc;
    char **argv;
    {
      int i;
      int j, top;
      
      i = 3;
    
      if (argc != 2) {
        fprintf(stderr, "Usage: spin iter-before-write\n");
        exit(1);
      }
      top = atoi(argv[1]);
      if (top <= 0) {
        while (1) {
          i = -i;
        }
      } else {
        while (1) {
          for (j = 0; j < top; j++) i = -i;
          write(1, "a", 1);
        }
      }
    }
    
    Spintest is a shell script that forks off a spin process at a given nice value, and then prints out the output of ``ps -l'' on that process for a given number of iterations at a given interval. For example, the following forks off ``spin 0'' with a nice value of zero for 20 seconds, printing out ps -l every second (this output is in spintest.out.0.0.1.20):
    UNIX> spintest 0 0 1 20
    20008001 192 18478 18476 12  28  0  20  152          R    p6  0:00 spin 0
    20008001 192 18478 18476 73  43  0  20  148          R    p6  0:02 spin 0
    20008001 192 18478 18476 64  41  0  20  148          R    p6  0:03 spin 0
    20008001 192 18478 18476 73  43  0  20  148          R    p6  0:04 spin 0
    20008001 192 18478 18476 68  42  0  20  148          R    p6  0:05 spin 0
    20008001 192 18478 18476 48  37  0  20  148          R    p6  0:06 spin 0
    20008001 192 18478 18476 39  34  0  20  148          R    p6  0:07 spin 0
    20008001 192 18478 18476 88  47  0  20  148          R    p6  0:08 spin 0
    20008001 192 18478 18476 72  43  0  20  148          R    p6  0:09 spin 0
    20008001 192 18478 18476 58  39  0  20  148          R    p6  0:10 spin 0
    20008001 192 18478 18476108  52  0  20  148          R    p6  0:11 spin 0
    20008001 192 18478 18476 92  48  0  20  148          R    p6  0:12 spin 0
    20008001 192 18478 18476 76  44  0  20  148          R    p6  0:13 spin 0
    20008001 192 18478 18476126  56  0  20  148          R    p6  0:14 spin 0
    20008001 192 18478 18476114  53  0  20  148          R    p6  0:15 spin 0
    20008001 192 18478 18476 94  48  0  20  148          R    p6  0:16 spin 0
    20008001 192 18478 18476149  62  0  20  148          R    p6  0:17 spin 0
    20008001 192 18478 18476138  59  0  20  148          R    p6  0:18 spin 0
    20008001 192 18478 18476122  55  0  20  148          R    p6  0:19 spin 0
    20008001 192 18478 18476108  52  0  20  148          R    p6  0:20 spin 0
    spintest: 19845 Killed
    UNIX>
    
    Note that the 6th field is the priority, and the 7th is the nice value. So, the priority of the spin process ranged between 34 and 55. You can use the avgprio program to print out the average priority of a process, by using the output of spintest. On the above output, it shows an average priority of 46.3.

    Note that I was doing nothing else on my machine while this ran. Note also that the priority of the program is not fixed over time, and that it does not hover around the nice value. This is because it is merely a function of the nice value and other things. Note that even though the priority appears to be a high number (46.3), the process got 20 seconds of cpu time over the 20 seconds that spintest was running. This is because there were no other processes (save (spintest) were executing at that time.

    Now I tried spintest using a nice value of 5 (output in spintest.out.0.5.1.20):

    UNIX> spintest 0 5 1 20
    20008001 192 18590 18589 57  49  5  20  152          R N  p6  0:00 spin 0
    20008001 192 18590 18589 44  46  5  20  148          R N  p6  0:01 spin 0
    20008001 192 18590 18589 32  43  5  20  148          R N  p6  0:02 spin 0
    20008001 192 18590 18589 72  53  5  20  148          R N  p6  0:03 spin 0
    20008001 192 18590 18589 54  48  5  20  148          R N  p6  0:04 spin 0
    20008001 192 18590 18589 41  45  5  20  148          R N  p6  0:06 spin 0
    20008001 192 18590 18589 74  53  5  20  148          R N  p6  0:06 spin 0
    20008001 192 18590 18589 62  50  5  20  148          R N  p6  0:07 spin 0
    20008001 192 18590 18589 49  47  5  20  148          R N  p6  0:08 spin 0
    20008001 192 18590 18589 92  58  5  20  148          R N  p6  0:09 spin 0
    20008001 192 18590 18589 74  53  5  20  148          R N  p6  0:11 spin 0
    20008001 192 18590 18589 59  49  5  20  148          R N  p6  0:11 spin 0
    20008001 192 18590 18589104  61  5  20  148          R N  p6  0:12 spin 0
    20008001 192 18590 18589 87  56  5  20  148          R N  p6  0:13 spin 0
    20008001 192 18590 18589 69  52  5  20  148          R N  p6  0:15 spin 0
    20008001 192 18590 18589116  64  5  20  148          R N  p6  0:16 spin 0
    20008001 192 18590 18589 99  59  5  20  148          R N  p6  0:17 spin 0
    20008001 192 18590 18589 80  55  5  20  148          R N  p6  0:18 spin 0
    20008001 192 18590 18589 70  52  5  20  148          R N  p6  0:19 spin 0
    20008001 192 18590 18589110  62  5  20  148          R N  p6  0:20 spin 0
    spintest: 19847 Killed
    UNIX>
    
    The average priority value is higher now (52.75) but the program still gets all of the cpu because there are no competing processes.

    Now, I ran ``spintest 0 0 1 20'' simultaneously in two windows. Here is the output of one of these (spintest.out.0.0.1.20.compete):

    UNIX> spintest 0 0 1 20
    20008001 192 20020 20019 27  31  0  20  160          R    p6  0:00 spin 0
    20008001 192 20020 20019 29  32  0  20  148          R    p6  0:01 spin 0
    20008001 192 20020 20019 49  37  0  20  148          R    p6  0:01 spin 0
    20008001 192 20020 20019 41  35  0  20  148          R    p6  0:01 spin 0
    20008001 192 20020 20019 45  36  0  20  148          R    p6  0:02 spin 0
    20008001 192 20020 20019 53  38  0  20  148          R    p6  0:02 spin 0
    20008001 192 20020 20019 51  37  0  20  148          R    p6  0:03 spin 0
    20008001 192 20020 20019 52  38  0  20  148          R    p6  0:03 spin 0
    20008001 192 20020 20019 54  38  0  20  148          R    p6  0:03 spin 0
    20008001 192 20020 20019 58  39  0  20  148          R    p6  0:04 spin 0
    20008001 192 20020 20019 66  41  0  20  148          R    p6  0:04 spin 0
    20008001 192 20020 20019 72  43  0  20  148          R    p6  0:05 spin 0
    20008001 192 20020 20019 62  40  0  20  148          R    p6  0:05 spin 0
    20008001 192 20020 20019 67  41  0  20  148          R    p6  0:05 spin 0
    20008001 192 20020 20019 75  43  0  20  148          R    p6  0:06 spin 0
    20008001 192 20020 20019 73  43  0  20  148          R    p6  0:06 spin 0
    20008001 192 20020 20019 69  42  0  20  148          R    p6  0:07 spin 0
    20008001 192 20020 20019 71  42  0  20  148          R    p6  0:07 spin 0
    20008001 192 20020 20019 75  43  0  20  148          R    p6  0:07 spin 0
    20008001 192 20020 20019 76  44  0  20  148          R    p6  0:08 spin 0
    spintest: 20020 Killed
    UNIX>
    
    This gives an average priority of 39.15, which is a much lower number than the first time we ran spintest. Why? Because one of the things that can lower a process's priority is spending more time in the ready queue. However, a lower priority does not translate into more CPU usage -- because there are two competing processes with roughly the same priority, each gets an equal amount of the CPU. In this case, each it amounts to less than half the CPU (8 seconds overall). Why not 10 seconds? Because there is significant context switch overhead.

    Finally, I ran ``spintest 0 0 1 20'' in one window, and ``spintest 0 5 1 20'' in another. The output of each is as follows:

    (This in spintest.out.0.0.1.20.compete):

    UNIX> spintest 0 0 1 20
    20008001 192 19046 19045 28  32  0  20  148          R    p5  0:00 spin 0
    20008001 192 19046 19045 38  34  0  20  148          R    p5  0:00 spin 0
    20008001 192 19046 19045 55  38  0  20  148          R    p5  0:01 spin 0
    20008001 192 19046 19045 48  37  0  20  148          R    p5  0:02 spin 0
    20008001 192 19046 19045 62  40  0  20  148          R    p5  0:02 spin 0
    20008001 192 19046 19045 66  41  0  20  148          R    p5  0:03 spin 0
    20008001 192 19046 19045 71  42  0  20  148          R    p5  0:03 spin 0
    20008001 192 19046 19045 62  40  0  20  148          R    p5  0:04 spin 0
    20008001 192 19046 19045 61  40  0  20  148          R    p5  0:05 spin 0
    20008001 192 19046 19045 70  42  0  20  148          R    p5  0:05 spin 0
    20008001 192 19046 19045 82  45  0  20  148          R    p5  0:06 spin 0
    20008001 192 19046 19045 89  47  0  20  148          R    p5  0:06 spin 0
    20008001 192 19046 19045100  50  0  20  148          R    p5  0:07 spin 0
    20008001 192 19046 19045 83  45  0  20  148          R    p5  0:07 spin 0
    20008001 192 19046 19045 96  49  0  20  148          R    p5  0:08 spin 0
    20008001 192 19046 19045101  50  0  20  148          R    p5  0:08 spin 0
    20008001 192 19046 19045102  50  0  20  148          R    p5  0:09 spin 0
    20008001 192 19046 19045 90  47  0  20  148          R    p5  0:09 spin 0
    20008001 192 19046 19045 95  48  0  20  148          R    p5  0:10 spin 0
    20008001 192 19046 19045108  52  0  20  148          R    p5  0:10 spin 0
    UNIX>
    
    This has an average priority of 43.45.

    And this in spintest.out.0.5.1.20.compete:

    UNIX> spintest 0 5 1 20
    20008001 192 19043 19042 20  40  5  20  152          R N  p6  0:00 spin 0
    20008001 192 19043 19042 28  42  5  20  156          R N  p6  0:00 spin 0
    20008001 192 19043 19042 27  41  5  20  148          R N  p6  0:00 spin 0
    20008001 192 19043 19042 35  43  5  20  148          R N  p6  0:00 spin 0
    20008001 192 19043 19042 46  46  5  20  148          R N  p6  0:01 spin 0
    20008001 192 19043 19042 45  46  5  20  148          R N  p6  0:01 spin 0
    20008001 192 19043 19042 41  45  5  20  148          R N  p6  0:01 spin 0
    20008001 192 19043 19042 40  45  5  20  148          R N  p6  0:01 spin 0
    20008001 192 19043 19042 42  45  5  20  148          R N  p6  0:01 spin 0
    20008001 192 19043 19042 45  46  5  20  148          R N  p6  0:02 spin 0
    20008001 192 19043 19042 55  48  5  20  148          R N  p6  0:02 spin 0
    20008001 192 19043 19042 65  51  5  20  148          R N  p6  0:02 spin 0
    20008001 192 19043 19042 59  49  5  20  148          R N  p6  0:03 spin 0
    20008001 192 19043 19042 64  51  5  20  148          R N  p6  0:03 spin 0
    20008001 192 19043 19042 71  52  5  20  148          R N  p6  0:03 spin 0
    20008001 192 19043 19042 70  52  5  20  148          R N  p6  0:03 spin 0
    20008001 192 19043 19042 70  52  5  20  148          R N  p6  0:04 spin 0
    20008001 192 19043 19042 66  51  5  20  148          R N  p6  0:04 spin 0
    20008001 192 19043 19042 72  53  5  20  148          R N  p6  0:04 spin 0
    20008001 192 19043 19042 75  53  5  20  148          R N  p6  0:04 spin 0
    
    This has an average priority of 47.55. Note that the first spintest process got more than twice the CPU of the second one.
    I won't go into it, but test and see if writing to standard output helps or hurts a process's priority. (i.e. give spin a value like 100000).