Exam 2025-2026
- Duration : 3 h
- During this exam, you may use any document, and you can search for information on the Internet
- Communicating with other people, or using AI to generate code is prohibited
Organization
Preparation
Returning your work
At the end of the exam, you have to post your work on moodle.
Please post a tgz file. You can generate it with:
Message board (9 points)
The files related to this exercise are located in the exercise2 directory.
The goal of this exercise is to implement a message board where multiple users can display messages. This message board consists of two parts:
- A server that creates a shared memory segment where clients can send messages. When a client adds a message to the shared memory segment, the server prints it in the terminal
- A client that adds messages to the shared memory segment.
The shared memory segment should contain a struct shared_memory (defined in message_board.h). This data structure contains an array of struct msg. To add a message to the message board, a client fills a struct msg and increments nb_messages.
client.c defines a function that generates random messages (void generate_message(struct msg* msg)). message_board.c defines a function that displays a message (void print_message(int index, struct msg* msg))
The output of message_board should look like this:Implementing the message board server (6 points)
Modify message_board.c so that it creates a shared memory segment that contains a struct shared_memory and initialize it. The program should then run a loop that displays messages (using display_message) when they are added to the shared memory.
After 5 messages, the program should detach from the shared memory segment, destroy it, and terminate.
Implementing a client (3 points)
We now implement the client in client.c. The client should open the shared memory segment, add a message to the message board, and detach from the shared memory segment.
Parallel processing (7 points)
The files related to this exercise are located in the exercise3 directory.
The goal of this exercise is to implement an application that uses several threads to process streaming data in parallel.
- A generator thread generates packets of data (represented as struct data) and send them to worker threads. A packet of data is an array of random numbers created by struct data* generate_data(). In this exercise, the generator will generate NB_PACKETS packets of data. The generator can start generating a packet only after the previous packet was fully processed by worker threads.
- When a packet of data is created, NB_THREADS worker threads are in charge of processing it. void process_data_serial() shows the expected processing of data_to_process if it were run using one thread. If the packet of data contains 100 values, 4 threads may process them by assigning values 0-24 to the first thread, values 25-49 to the second thread, values 50-74 to the third thread, and values 75-99 to the fourth thread.
3 points
First, the main function should create one generator thread, and wait for its termination. The generator thread generates NB_PACKETS packets of data. For each packet of data to create, the generator:
- waits until the previous packet of data was fully processed.
- generates a new packet of data (by calling generate_data)
- notifies the worker threads that a packet needs to be processed
4 points
Next, modify the main function so that it creates NB_THREADS worker threads and waits for their termination. For each of the NB_PACKETS packets to process, each worker thread should:
- Wait for a packet of data to be generated
- Process a part of the packet of data
Once the worker threads have all processed the packet of data, one of them should compute the average value and call print data. The generator thread can then generate a new packet of data.
xv6 - process depth (6 points)
The files related to this exercise are located in the exercise4 directory.
In this exercise, you are asked for xv6 code. You don't have to attach all the sources to your archive (that would be too big). Instead start by cloning xv6 outside of the directory where you did the other exercises with the following command:
At the end of the exam, generate a patch in the directory where you did the other exercises, run the following commands:
Where ${PATH_TO_CF} is the path to the directory containing the code you did for the other exercises.
The goal of this exercise is to implement a new system call int process_depth(int pid). This system call returns the "depth" of process whose PID is pid. The "depth" of a process is defined as it number of ancestors. For example, the depth of sh is 1 because its parent process is the root process, and the depth of command ls is 2 because its parent is the sh process.
Adding a system call (3.5 points)
Add a new the system call int process_depth(int pid) in xv6. You can implement the corresponding kernel function in proc.c.
The implementation of this system call should:
- Check that PID pid corresponds to a usable process (based on its status). In case of an error, print an error message and return -1.
- Browse the process parent until reaching the root process (whose parent is NULL), and return the requested process' depth.
2.5 point
Create a test program test_process_depth.c that:
- Prints the depth of the current process (eg. "My depth: 2");
- Create a child process. The child process should sleep for 1 second before terminating
- Meanwhile, the parent process should print the depth of the child process (eg. "Child process depth: 3")