Study Guide: OS Exam I

Exams are closed book. You can bring one written cheat sheet. 90 minutes in class.

Topics:

  • Tanenbaum Chapter 1-2, 6

  • Command line and terminal

  • Files: stdin, stdout, stderr, text and binary files

  • System calls: files, processes, signals, context switching

  • Basic POSIX threads: pthread, wait, barrier, mutex, conditionals

Tanenbaum

  • Chapter 1: 1, 3, 6, 9, 10, 12, 13, 17, 20, 23, 26, 28, 30

  • Chapter 2: 5, 6, 7, 8, 12, 13, 14, 15, 16, 17, 18, 19, 25, 26, 30, 36, 40, 42, 43, 44, 45, 47, 48, 49, 50, 51, 64, 65

  • Chapter 6: 2, 3, 10, 14, 15, 16, 22, 24, 26, 27, 30, 34, 35, 39, 40

Additional practice

OS

  1. What is an operating system?

  2. What are examples of abstractions that the OS maintains that make using computer hardware easier?

  3. What is multiprogramming?

  4. What are some challenges of designing/implementing an OS that supports multi-programming?

  5. What are the two main purposes of the operating system?

  6. What is the difference between an interrupt and a trap?

  7. What features do interrupts and traps implement in an OS?

  8. What is the advantage of using interrupts and traps for an OS implementation. In other words, if an OS were not designed with these features, how would it change the design of modern operating systems.

  9. What is the kernel?

  10. What is the difference between kernel mode and user mode?

  11. What is a system call? How are system calls different from user-defined functions?

  12. How are errors reported with most system calls?

Programming

  1. What is a function pointer?

  2. What is a void* pointer?

  3. What is a bit field?

  4. What is the output of the following program?

    #include <stdio.h>
    
    typedef void (*functionType)(int a, int b);
    
    void example(int a, int b) {
      printf("This is a function stored as data! %d %d\n", a, b);
    }
    
    int main() {
      functionType myFunction = example;
      (*myFunction)(10, 3);
    }
  5. Draw the stack diagram for the following program. Then indicate which of the following dereferences are safe.

    #include <stdio.h>
    
    int main()
    {
      void* generic = NULL;
      int a = 3;
      double b = 4.5;
      generic = &a;
      generic = &b;
    
      printf("test %f\n", *generic);
    
      double* double_ptr = (double *) generic;
      printf("test %f\n", *double_ptr);
    
      int* int_ptr = (int *) generic;
      printf("test %d\n", *int_ptr);
    
      generic = &a;
    
      double* double_ptr = (double *) generic;
      printf("test %f\n", *double_ptr);
    
      int* int_ptr = (int *) generic;
      printf("test %d\n", *int_ptr);
    
      return 0;
    }
  6. Draw the stack diagram for the following program. What is the output?

    #include <stdio.h>
    #include <string.h>
    
    char* foo(char* str, char c)
    {
      int n = strlen(str);
      for(int i = 0; i < n; i++)
      {
        if (str[i] == c)
        {
          str[i] = '\0';
          return str;
        }
      }
      return NULL;
    }
    
    int main()
    {
      char buffer[8];
      strcpy(buffer, "a,b,c");
    
      char* s = foo(buffer, ',');
      printf("%s\n", s);
    }
  7. Consider the following code. Assume that sigset_t is a 32-bit unsigned integer. Express your answers as a hexadecimal value.

    1 sigset_t newset;
    2 sigemptyset(&newset);
    3 sigaddset(&newset, SIGTTIN);
    4 sigaddset(&newset, SIGTTOU);
    5 sigfillset(&newset);
    • What is the value of newset after executing line 2.

    • What is the value of newset after executing line 3. Assume that SIGTTIN has the value (0x1 << 21).

    • What is the value of newset after executing line 4. Assume that SIGTTOU has the value (0x1 << 22).

    • What is the value of newset after executing line 5.

  8. What is the output of the following program?

    void f(){
      int i = 0;
      while (i < 3) {
        printf("i = %d\n", i);
        i++;
      }
      swapcontext(&uc, &mainc);
      while (i < 6) {
        printf("i = %d\n", i);
        i++;
      }
    }
    
    int main(int argc, char * argv[]){
    
      getcontext(&uc); // initialize context
    
      // setup stack and signal handling
      void* stack = malloc(STACKSIZE);
      uc.uc_stack.ss_sp = stack;
      uc.uc_stack.ss_size = STACKSIZE;
      uc.uc_stack.ss_flags = SS_DISABLE;
      sigemptyset(&(uc.uc_sigmask));
      uc.uc_link = &mainc;
      makecontext(&uc, f, 0);
    
      swapcontext(&mainc, &uc);
      printf("Back in main 1\n");
      swapcontext(&mainc, &uc);
      printf("Back in main 2\n");
      return 0;
    }

Shell, command line, files

  1. What is a file? A directory?

  2. What are some common file types?

  3. What is the difference between text and binary files?

  4. How do we distinguish between file types?

  5. In a file system, what is a path?

  6. What is the difference between an absolute and relative path?

  7. What is the current working directory?

  8. What is the difference between a foreground and background process in the terminal?

  9. What is a pipe? Give an example of a bash command that uses pipes.

  10. How is redirected input/output different from reading/writing a file?

  11. What is job control in regards to the bash terminal?

  12. How do you redirect output to a file in terminal?

  13. What do the file descriptors corresponding to values 0, 1, and 2 represent in terminal?

  14. What is a process group?

  15. What is a session?

  16. What is the controlling terminal for a process?

  17. What do the following symbols mean when they are in a path?

    • /

    • .

    • ..

    • ~

  18. Suppose a file system has the following hierarchy

    root
    + home
    ++ ren
    +++ A
    ++ stimpy
    +++ B
    +++ C
    ++++ hello.txt
    • What is the absolute path of hello.txt?

    • If we are in the directory A, what is the relative path of hello.txt?

    • If we are in the directory B, what is the relative path of hello.txt?

  19. Draw the directory hierarchy after the following commands

    $ pwd
    /home/alinen
    $ mkdir A
    $ cd A
    $ mkdir Z
    $ touch talk.c
    $ cd ..
    $ touch listen.c
    $ cd
    $ touch sing.c
  20. Consider the following file properties listed with ls -l

    -rw-r--r--  0 alinen alinen   70 Dec 10  2023 README.md
    • What does the above file permissions represent?

    • What numeric value corresponds to the following permissions (in octal)? –rw-r—​r--

    • What numeric value corresponds to the following permissions (in octal)? –rwxr-x—​x

    • What permissions correspond to the value 0665?

  21. Consider the following commands and associated diagram.

processgroups
  • Fill in the session ID for each of the processes

  • Fill in the parent group IDs for each of the processes

  • Fill in the process group IDs for each of the processes. Assume that children are created with the call setpgid(0,0)

  • In the above diagram, what processes are running in the foreground?

  • In the above diagram, what processes are running in the background?

  • Suppose a user sends the following signal command. kill(658, SIGALRM) Which processes receive the signal?

  • Suppose a user sends the following signal command. kill(-658, SIGALRM) Which processes receive the signal?

  • Suppose a user sends the following signal command. kill(659, SIGALRM) Which processes receive the signal?

Processes

  1. What is a process?

  2. What is the difference between a process and a C program?

  3. What are the different states that a process might be in?

  4. Why might a processed be in a blocked state?

  5. Why do we need special mechanisms, such as pipes or sockets, to communicate between processes?

  6. How can you kill a process using ps ?

  7. What is a zombie process?

  8. What is an orphan process?

  9. What is a signal? what is a signal handler?

  10. Some signals cannot be ignored. Name a signal that cannot be ignored and explain why a program cannot ignore it.

  11. Why might we want to register a signal handler?

  12. When a signal arrives to a process, list three ways the process can respond to the signal.

  13. What happens when multiple signals arrive to a process before a process is able to process them?

  14. When does the OS send the SIGSEGV signal?

  15. When does the OS send the SIGINT signal?

  16. When does the OS send the SIGCHD signal?

  17. What signal is sent when the user types Ctrl-Z at the terminal?

  18. What happens when a process calls fork?

  19. What happens when a signal arrives for a process?

  20. What type of event does SIGINT represent? Sketch a program that registers a signal handler for SIGINT?

  21. What does the execv family of commands do? How do fork and execv compare?

  22. What different regions are present within the memory layout of a process?

  23. What is the process control block?

  24. What is the program counter?

  25. When are processes created? destroyed? blocked?

  26. How many processes are created for the command ls *.c | grep apple?

  27. The following program creates a zombie process. Why?

    void main() {
      if (fork() == 0) { /*child */
        printf("Child, PID = %d\n", getpid());
        exit(0);
      } else { /*parent */
        printf("Parent, PID = %d\n", getpid());
        while(1) {
        }
      }
    }
  28. Draw the process timeline created by executing the following program. For each created process, list its output (e.g. what does each process print)?

    int main() {
      pid_t ret;
    
      printf("A\n");
    
      ret = fork();
      if(ret == 0) {
        printf("B\n");
    
        ret = fork();
        if(ret == 0) {
          printf("C\n");
        }
        printf("D\n");
      } else {
        printf("E\n");
    
        ret = fork();
        printf("F\n");
      }
    
      printf("G\n");
      return 0;
    }
  29. Draw the process timeline created by executing the following program. For each created process, list its output (e.g. what does each process print)? How many processes are created?

    int main() {
      pid_t ret;
    
      printf("A\n");
    
      for (int i = 0; i < 3; i++)
      {
         ret = fork();
         if (ret == 0) // child
         {
            printf("B%d\n", i);
         }
      }
    
      printf("Z\n");
      return 0;
    }
  30. Draw the process timeline created by executing the following program. For each created process, list its output (e.g. what does each process print)? How many processes are created?

    int main() {
      pid_t ret;
    
      printf("A\n");
    
      for (int i = 0; i < 3; i++)
      {
         ret = fork();
         if (ret == 0) // child
         {
            printf("B%d\n", i);
            exit(0);
         }
      }
    
      printf("Z\n");
      return 0;
    }
  31. Draw the process timeline created by executing the following program. For each created process, list its output (e.g. what does each process print)? How many processes are created?

    int main() {
      pid_t ret;
    
      int value = 10;
      printf("A%d\n", value);
    
      ret = fork();
      if (ret == 0) // child
      {
         value--;
      }
      else
      {
         value++;
      }
    
      printf("Z%d\n", value);
      return 0;
    }
  32. Implement a program whose behavior matches the given timeline.

    processes

Threads

  1. What is a thread? How does a thread differ from a process? How are threads similar?

  2. Why and when might we want to use multiple threads to implement a program?

  3. Why and when might we want to use multiple processes to implement a program?

  4. Explain how threads might improve the implementation of a word processor.

  5. Explain how threads might improve the implementation of a web server.

  6. Explain how threads might improve the implementation of a web server.

  7. How do threads created in user space differ from threads created in kernel space?

  8. What is a critical section?

  9. What is a race condition?

  10. What is mutual exclusion?

  11. What is deadlock? livelock?

  12. What is bounded liveness?

  13. What four criteria must be met to ensure mutual exclusion?

  14. Why is disabling interrupts not ideal for enforcing mutual exclusion?

  15. Sketch a multi-threaded program (N threads) that computes the average of a list of numbers. You can assume that the size of the list can be evenly divided by N.

  16. Draw the stack diagram for the following program with two threads.

    struct foo {
       long id;
       char message[16];
    };
    
    void *HelloWorld(void *id) {
      struct foo *holder = (struct foo *) id;
      printf("%s world! I am thread %ld\n", holder->message, holder->id);
      return NULL;
    }
    
    int main(int argc, char **argv) {
      struct foo holder1, holder2;
      holder1.id = 1;
      strcpy(holder1.message, "caio");
    
      holder2.id = 2;
      strcpy(holder2.message, "aloha");
    
      long* retval1 = NULL, *retval2 = NULL;
      pthread_t thread1, thread2;
      pthread_create(&thread1, NULL, HelloWorld, &holder1);
      pthread_create(&thread2, NULL, HelloWorld, &holder2);
      pthread_join(thread1, NULL);
      pthread_join(thread2, NULL);
      return 0;
    }
  17. Explain why the following program does not compute the correct answer for count.

    #define MAX 100000
    int count=0;
    
    void interleave() {
      pthread_t th0, th1;
      pthread_create(&th0,0,test,0);
      pthread_create(&th1,0,test,0);
      pthread_join(th0,0);
      pthread_join(th1,0);
      printf(“%d\n”, count);
    }
    
    void test() {
      for(int j=0;j<MAX;j++) count=count+1;
    }
  18. For the following sets of assembly instructions for processes 1 and 2, give an interleaving of instructions that results in v having the value 2.

    P1. MOVE V, r0			Q1. MOVE V, r1
    P2. INCR r0			    Q2. INCR r1
    P3. MOVE r0, V			Q3. MOVE r1, V
  19. For the following sets of assembly instructions for processes 1 and 2, give an interleaving of instructions that results in v having the value 3.

    P1. MOVE V, r0			Q1. MOVE V, r1
    P2. INCR r0			    Q2. INCR r1
    P3. MOVE r0, V			Q3. MOVE r1, V
  20. Consider the following code for a process P0. Assume that the code for P1 is symmetric. Is it possible for both P0 and P1 to be in the same critical section at the same time?

    Shared variable: turn :{0,1}
    while (TRUE) {
      while (turn != 0);  /* busy waiting */
      CS();
      turn = 1; /* let the other enter */
      Non_CS();
    }
  21. Consider the following code for a process P0. Assume that the code for P1 is symmetric. Is it possible for both P0 and P1 to be in the same critical section at the same time?

    Shared variable: interested[i] : int, init 0
    while (TRUE) {
      interested[0] = 10;
      while (interested[1] > 0) interested[0]--;
      CS();
      interested[0] = 0;
      Non_CS();
    }
    • If P0 is in the critical section, what values should interested have?

    • If P1 is in the critical section, what values should interested have?

    • Is it possible for both P0 and P1 to be in the same critical section at the same time?

  22. Consider the following code for a process P0. Assume that the code for P1 is symmetric.

    Shared variables: interested[i] :boolean;
                      turn :{0,1}
    interested[0] = FALSE;
    while (TRUE) {
      interested[0] = TRUE;  /* declare interest */
      turn = 0; /* takes care of race condition */
      repeat if /* busy wait */
       (interested[1] == TRUE && turn == 0);
      CS();
      interested[0] = FALSE; /* unblock P1 */
      Non_CS();
    }
    • If P0 is in the critical section, what values should interested and turn have?

    • If P1 is in the critical section, what values should interested and turn have?

    • Is it possible for both P0 and P1 to be in the same critical section at the same time?

  23. Consider the producer/consumer problem discussed in class. Suppose the buffer has size 8 and contains the values -2,3,4,-5; that in = 7 and out = 3.

    • Draw the state of the buffer, in, out, and num_items.

    • Suppose the producer adds one item. Draw the new state of the buffer.

    • Suppose the consumer removes 3 items. Draw the new state of the buffer.

  24. Consider the following implementation for two threads, one a producer and the other a consumer. Does the code below contain a race condition? If yes, explain how the current implementation can lead to inconsistent buffer state.

    //Producer Threads:
    int item;
    while(1) {
      item = produce_item();
      pthread_mutex_lock(&mux);
      buff[in] = item;
      in = (in+1)%N;
      pthread_mutex_unlock(&mux);
      num_items++;
    }
    //Consumer thread
    int item;
    while(1) {
      pthread_mutex_lock(&mux);
      item = buff[out];
      out = (out+1)%N;
      pthread_mutex_unlock(&mux);
      num_items--;
      consume_item(item);
    }

Scheduling

  1. How does a CPU-bound process differ from an IO-bound process?

  2. What does it mean for a scheduling algorithm to be preemptive? non-preemptive?

  3. What are the advantages and disadvantages of the FCFS scheduling algorithm. Give a class of applications where FCFS is the best scheduling policy.

  4. What are the advantages and disadvantages of the SJF scheduling algorithm. Give a class of applications where FCFS is the best scheduling policy.

  5. What are the advantages and disadvantages of the RR scheduling algorithm. Give a class of applications where FCFS is the best scheduling policy.

  6. How do the needs of real-time systems differ from other application domains?

  7. What is priority inversion? How can we avoid it?

  8. Suppose we have a batch system with the following jobs, scheduled with FCFS. Job 1: 15 units, Job 2: 8 units, Job 1: 1 units.

    • Show the timeline of jobs based on this scheduling strategy.

    • What is the average waiting time?

    • What is the average turnaround time?

  9. Suppose we have a batch system with the following jobs, scheduled with SJF. Job 1: 15 units, Job 2: 8 units, Job 1: 1 units.

    • Show the timeline of jobs based on this scheduling strategy.

    • What is the average waiting time?

    • What is the average turnaround time?

  10. Suppose we have a batch system with the following jobs, scheduled with RR and a quantum of 5. Job 1: 15 units, Job 2: 8 units, Job 1: 1 units.

    • Show the timeline of jobs based on this scheduling strategy.

    • What is the average waiting time?

    • What is the average turnaround time?

  11. Suppose we have a batch system with the following jobs, scheduled with HPF and a quantum of 5. Assume all jobs start with the same priority. Job 1: 15 units, Job 2: 8 units, Job 1: 1 units.

    • Show the timeline of jobs based on this scheduling strategy.

    • What is the average waiting time?

    • What is the average turnaround time?

  12. Suppose we have a batch system with the following jobs, scheduled with HPF and a quantum of 5. Assume Job 2 has higher priority than Jobs 1 and 2. Job 1: 15 units, Job 2: 8 units, Job 1: 1 units.

    • Show the timeline of jobs based on this scheduling strategy.

    • What is the average waiting time?

    • What is the average turnaround time?

  13. Suppose we are scheduling three tasks for a real-time system using EDF. What is the utilization of these tasks? Show the scheduling order.

    • Task T1 with period 10 and CPU time 3

    • Task T2 with period 10 and CPU time 1

    • Task T3 with period 15 and CPU time 8

Deadlocks

  1. What is a deadlock?

  2. Name four conditions for deadlock.

  3. List four ways to deal with deadlock.

  4. Under what circumstances is ignoring deadlock a reasonable strategy? Under what circumstances is it unacceptable?

  5. What factors does the OS need to keep track of in order to detect deadlocks?

  6. List three ways that the OS can recover from deadlock if it is detected.

  7. Give an example of deadlock recovery through preemption.

  8. Give an example of deadlock recovery through rollback.

  9. Give an example of deadlock recovery through killing a process.

  10. Give an example of deadlock prevention by removing the need for "mutual exclusion".

  11. Give an example of deadlock prevention by avoid the need for "hold and wait" of resources.

  12. Give an example of deadlock prevention by allowing resources to be "preempted".

  13. Give an example of deadlock prevention by avoid the need for "circular wait" of resources.

  14. What is a safe state?

  15. Does an unsafe state guarantee a deadlock will occur? Why or why not?

  16. Consider 5 dining philosophers. Can the following code deadlock? Why or why not?

    pthread_mutex_t mutex[N]
    struct thread_data {
      int id;
    };
    
    void Philosophize(void* usr)
    {
      struct thread_data* data = (struct thread_data*) usr;
      printf("%d is hungry\n", data->id);
    
      int leftFork = data->id;
      int rightFork = (data->id + 1) % N;
    
      pthread_mutex_lock(&mutex[leftFork]);
      pthread_mutex_lock(&mutex[rightFork]);
      printf("%d is eating\n", data->id);
      sleep(duration);
      pthread_mutex_unlock(&mutex[leftFork]);
      pthread_mutex_unlock(&mutex[rightFork]);
    }
  17. Consider 5 dining philosophers. Can the following code deadlock? Why or why not. Is the given solution fair?

    pthread_mutex_t mutex[N]
    struct thread_data {
      int id;
    };
    
    void Philosophize(void* usr)
    {
      struct thread_data* data = (struct thread_data*) usr;
      printf("%d is hungry\n", data->id);
      if (data->id % 2 == 0) return;
    
      int leftFork = data->id;
      int rightFork = (data->id + 1) % N;
    
      pthread_mutex_lock(&mutex[leftFork]);
      pthread_mutex_lock(&mutex[rightFork]);
      printf("%d is eating\n", data->id);
      sleep(duration);
      pthread_mutex_unlock(&mutex[leftFork]);
      pthread_mutex_unlock(&mutex[rightFork]);
    }
  18. Consider 5 dining philosophers. Can the following code deadlock? Why or why not. Is the given solution fair?

    pthread_mutex_t mutex[N]
    struct thread_data {
      int id;
    };
    
    void Philosophize(void* usr)
    {
      struct thread_data* data = (struct thread_data*) usr;
      printf("%d is hungry\n", data->id);
      if (data->id % 2 == 0) return;
    
      int leftFork = data->id;
      int rightFork = (data->id + 1) % N;
    
      pthread_mutex_lock(&mutex[leftFork]);
      pthread_mutex_lock(&mutex[rightFork]);
      printf("%d is eating\n", data->id);
      sleep(duration);
      pthread_mutex_unlock(&mutex[leftFork]);
      pthread_mutex_unlock(&mutex[rightFork]);
    }
  19. Visualize the following requests for resources using a resource allocation graph. Does deadlock occur?

    A requests R
    B requests S
    C requests T
    A requests S
    B requestsT
    C requests R
  20. Visualize the following resource/usage state using matrices. Is there deadlock?

    • Suppose there are 2 instances of A and 3 of B

    • Process P currently has 1 instance of A, and is requesting 1 instance of A and 3 instances of B

    • Process Q currently has 1 instance of B, and is requesting 1 instance of A and 1 instance of B

  21. Is the following a safe state?

    Process     Holding     Max
    A           4           6
    B           4           11
    C           2           7
    
    Unallocated: 2
  22. Is the follow state with multiple resources safe? If so, show the sequence of allocations that avoid deadlock. If so, show the sequence of allocations that avoid deadlock. Otherwise, show why deadlock is possible.

BankersAlgorithmMultiResources