CS2020 2021
CS2020 2021
CS2020 2021
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int i = fork() && (fork() || fork());
printf("fork! (%d, %d, %d)\n", getpid(), getppid(), i);
exit(EXIT_SUCCESS);
}
1. Que fait ce programme ? Dessiner un arbre des processus avec la valeur de i à chaque étape.
Indice : Il n’y aura pas 8 processus.
2. Écrire un programme qui, pour un n ≥ 0 donné, engendre un arbre généalogique linéaire de n
générations de fils (sans aucun frère). Chaque fils crée tire un int au hasard. Le programme
initial (le père) affiche la plus grande des valeurs aléatoires tirées par les fils.
Exercice 3 : Mémoire
Vous allez écrire un allocateur mémoire qui permet d’allouer efficacement des espaces mémoires
de tailles identiques. Pour accélérer les allocations, chaque appel à sbrk() demandera 10 fois plus
d’espace que nécessaire, cela permettra ainsi d’avoir déjà 9 blocs prêt à être alloué. Le cahier des
charges de l’API est le suivant :
• void *block_init(size_t x, int n) initialise l’allocateur pour qu’il puissent fournir à la demande n blocs
de x octets.
• void *block_alloc() retourne l’adresse d’un bloc de x octets vide. Le numéro du bloc sera stocké
juste avant cette adresse.
• void block_free(void* ptr) marque un bloc comme libre un bloc libérer, • void block_free_all()
libère tous les blocs alloués depuis l’appel à bloc_init.
Cet allocateur devra gérer les blocs alloués et désallouer, un bloc alloué sera marqué avec son
numéro de bloc (int placé juste avant le bloc), un bloc non alloué portera un numéro de bloc nul. Si
aucun bloc n’est disponible lors de l’appel à void *block_alloc(), alors un nouveau pool de n blocs sera
créé et ajouté à la liste chaînée.
Le header de la liste chaînée sera le suivant :
typedef struct BLOCK_TAG{
struct BLOCK_TAG *ptr_next; // pointe sur le prochain chainon
int n; // nombres de blocs
size_t x; // taille d'un bloc
} BLOCK_PTR;
BLOCK_PTR *head = NULL;
3/7
2. Proposer une implémentation de l’allocateur void *block_init(size_t x, int n) telle qu’il puisse aussi
être utilisé pour ajouter un nouveau pool.
void *block_init(size_t size, int n)
{
HEADER_TAG *head = sbrk(HEADER_SIZE + size);
head->ptr_next = NULL;
head->bloc_size = size;
4/7
5. Proposer une implémentation de void block_free_all().
Exercice 4 : Filesystem
1. Dessinez la structure de ce Filesystem sur le disque dur, en particulier le contenu des pre miers
blocs.
2. Combien d'inodes peut-on avoir au maximum sur un filesystem si on considère que la table
d’inodes tient forcément dans 1 seul bloc ?
3. Pour augmenter la taille des fichiers possibles, on considère Tos2FS où le champ d'indexation
direct block_no est remplacé par une indexation indirecte simple. Quelle est alors la taille
maximale d’un fichier en octets et en blocs ?
4. Quel est alors le nombre maximal de bloc possible pour l’ensemble du système de fichier
Tos2FS ?
Exercice 5 : Réseau
Un service de streaming en ligne de musique propose une API REST. Cette API permet de manipuler notamment les playlists des
utilisateurs à l’aide des ”end-points” suivants :
• POST /api/playlists/{playlist_id}/tracks
• POST /api/users/{user_id}/playlists
• GET /api/users/{user_id}/playlists
• GET /api/playlists/{playlist_id}/images
• GET /api/playlists/{playlist_id}
• GET /api/users/{user_id}/playlists
• DELETE /api/playlists/{playlist_id}/tracks
• PUT /api/playlists/{playlist_id}/tracks
• PUT /api/playlists/{playlist_id}/images
On suppose que chaque objet échangé est sous la forme json suivante :
{
'id': 12345,
'type': 'type de la ressource',
'name': 'nom de la ressource',
'data': données de la ressource
}
avec le type pouvant être égale à : ’playlist’, ’user’, ’artist’, ’tracks’, ’image’…
2. Quel end-point doit-on utiliser pour lister les pistes d’une playlist ?
GET /api/users/{user_id}/playlists
3. Quel end-point doit-on utiliser pour changer une piste d’une playlist ?
PUT /api/playlists/{playlist_id}/tracks
4. Quel end-point faudrait-il ajouter à cette liste pour effacer une playlist ?
DELETE /api/playlists/{playlist_id}