Table of Contents

Solution of exercises (Exam 2020/06/16 with exams platform)

Return to Operating Systems Course

Download text of exercises: 20200616e.pdf - exams platform

Solution

Textual solution: 20200616e_sol.pdf - exams platform

Video with the solution of all the exercises of the exam

Solution exercise 2

Text:

Describe the characteristics of the signals to send asynchronous information between processes. Implement the following program:

  1. Ordered List Item A program generates two processes P1 and P2 and it awaits for receiving signals from them. Every time it receives a message from P1 in displays on standard output the message “Signal received from P1”. Analogously, every time it receives a message from process P2 it displays the message “Signal received from P2”. If it receives 3 signals from the same process, it terminates processes P1 and P2 using the shell command “kill” and it terminates.
  2. Process P1 and P2 run through an infinite cycle. Within the cycle, they await for a random time and then send a signal to the parent. P1 sends signal SIGUSR1; P2 sends signals SIGUSR2.

Solution:

20200616e_ex2.c
/* Exam 2020/06/16 - Exercise 2 */
 
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
 
int last_sig = -1;
int last_last_sig = -1;
int finish = 0;
 
 
void sign_handler(int sig){
 
  if (sig==SIGUSR1) printf("Signal received from P1\n");
  else if (sig==SIGUSR2) printf("Signal received from P2\n");
 
  /* It receives 3 consecutive signals from the same process */
  if (sig == last_sig && last_sig == last_last_sig) {
    finish = 1;
  } else {
    last_last_sig = last_sig;
    last_sig = sig;
  }
}
 
 
int main() {
  char cmd[100];
  pid_t pid1, pid2;
 
  if ( (signal(SIGUSR1, sign_handler) == SIG_ERR) || (signal(SIGUSR2, sign_handler ) == SIG_ERR) ) {
    printf("Error initializing signal handler");
    exit(-1);
  }
 
  pid1 = fork();
  if (!pid1) {
    /* P1 */
    while (1) {
      sleep( rand()%2 );
      kill(getppid(), SIGUSR1);
    }
  } else {
    pid2 = fork();
    if (!pid2) {
      /* P2 */
      while (1) {
        sleep( rand()%3 );
        kill(getppid(), SIGUSR2);
      }
    }         
  }
 
  /* Parent */
  while (1) {
    pause();
    if (finish) {
      /* Kill P1 with a shell command */
      sprintf(cmd, "kill -9 %d", pid1);
      system(cmd);
      /* Kill P2 with a shell command */
      sprintf(cmd, "kill -9 %d", pid2);
      system(cmd);
      exit(0);
    }
  }
 
}

Solution exercise 4

Text:

Given a file named “file.txt” containing some words (i.e., sequences of alphabetic characters separated by spaces, even on multiple lines) with content similar to the following:

file.txt
one two three
four five six
seven

Implement a bash script that prints the word with longer length. Given the previous example, the script must print in output the word “three” or the word “seven”, because both have 5 characters.

Solution:

20200616e_ex4.sh
#!/bin/bash
# Exam 2020/06/16 - Exercise 4
 
longest_word=""
length_longest=0
 
# Scan the file word by word
for word in $(cat file.txt)
do
    # Detect the length of $word
    length=$(echo $word|wc -c)
    #length=${#word} # Other possibility
 
    if [ $length -gt $length_longest ]
    then
        length_longest=$length
        longest_word=$word
    fi
done
 
echo $longest_word

Solution exercise 7

Text:

A function is formed by two distinct sessions A and B, executed only once in sequence:

... f (...) {
 A
 B
}

The function is executed by N threads in parallel (with N integer value, defined but unknown), thus the user would like to synchronize the N threads such that section B is executed by a thread only after all threads have terminated the execution of section A. In other words, the N threads must synchronize after running on A and before one of them is running on B. Note that function f() can be executed by each process only once. Write the require C code to implement such a behavior.

Solution:

20200616e_ex7.c
/* Exam 2020/06/16 - Exercise 7 */
 
#define N ....
 
sem_t m;
sem_t b;
sem_t sync;
 
int nwait = 0;
 
 
void f(void) {
  A();
 
 
  /* Input barrier */
  sem_wait(&b);
  sem_post(&b);
 
  sem_wait(&m);
  nwait++;
  if(nwait==N){
    P(b); /* Close the input barrier */
    for(c=0; c<N; c++) sem_post(&sync);
  }
  sem_post(&m);
 
  sem_wait(&sync);
 
  sem_wait(&m);
  nwait--;
  /* When last thread exits (i.e., it passed sem_wait(&sync)), open the input barrier */
  if(nwait==0) sem_post(&b);
  sem_post(&m);
 
 
  B();
}
 
 
void thread(void *arg) {
 
  while (1) {
    f();
  }
 
}
 
 
int main() {
  sem_init(&m, 0, 1);
  sem_init(&b, 0, 1);
  sem_init(&sync, 0, 0);
 
  /* Threads generation */
  pthread_create(...);
 
  return 0;
}