{
  "chapter": {
    "id": "processus-systeme",
    "level": "terminale",
    "theme": "Architectures",
    "title": "Processus et système",
    "description": "Approfondissement de la gestion des processus par\nun système d'exploitation : notion de processus,\nétats, ordonnancement, communication entre\nprocessus, synchronisation par verrous, risque\nd'interblocage et notion de signal.",
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "processus"
      ],
      "title": "Notion de processus",
      "statement": "Qu'est-ce qu'un **processus** ?",
      "options": [
        {
          "text": "Le fichier exécutable rangé sur le disque, tel qu'il existe avant son lancement",
          "correct": false,
          "feedback": "Cette description correspond plutôt\nà un **programme** au sens du\nfichier exécutable. Un processus\nest, lui, dynamique : il représente\nun programme **en cours d'exécution**.\n"
        },
        {
          "text": "Un programme en cours d'exécution, avec sa mémoire et son contexte propres",
          "correct": true,
          "feedback": "C'est une abstraction centrale du\nsystème d'exploitation. Un même\nprogramme lancé deux fois donne\ndeux processus indépendants, qui\ndisposent chacun de leur propre\nmémoire et de leur propre contexte\nd'exécution.\n"
        },
        {
          "text": "Une zone particulière de la mémoire vive réservée par le noyau",
          "correct": false,
          "feedback": "Un processus utilise de la mémoire\n(sa zone de mémoire), mais il\nn'est pas lui-même un type de\nmémoire.\n"
        },
        {
          "text": "Une fonction particulière définie à l'intérieur d'un programme",
          "correct": false,
          "feedback": "Une fonction n'est qu'un fragment\nde code à l'intérieur d'un\nprogramme. Un processus est une\nnotion bien plus large, qui\nenglobe l'intégralité d'un\nprogramme en exécution.\n"
        }
      ],
      "explanation": "Il faut bien distinguer la notion de\n**programme** (un fichier exécutable\nsur le disque) et celle de **processus**\n(une instance dynamique de ce programme\nen cours d'exécution). Sous Linux, les\ncommandes `ps` ou `top` permettent\nd'observer les processus actifs ; sous\nWindows, on utilise le Gestionnaire des\ntâches."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "thread"
      ],
      "title": "Fil d'exécution",
      "statement": "Qu'est-ce qu'un **fil d'exécution**\n(parfois appelé *thread*) ?",
      "options": [
        {
          "text": "Un processus secondaire disposant de sa propre mémoire isolée",
          "correct": false,
          "feedback": "Erreur fréquente : c'est plutôt la\ndéfinition d'un processus. Les fils\nd'un même processus **partagent** la\nmémoire, ils ne sont pas isolés les\nuns des autres.\n"
        },
        {
          "text": "Une unité d'exécution légère interne à un processus, partageant sa mémoire",
          "correct": true,
          "feedback": "Plusieurs fils d'exécution dans un\nmême processus permettent de\nparalléliser des tâches tout en\npartageant les données. Cette\napproche est plus légère que de\ncréer plusieurs processus, mais\nplus délicate à gérer en raison\ndes problèmes de synchronisation.\n"
        },
        {
          "text": "Une copie complète du programme, exécutée en parallèle sur un autre cœur du processeur",
          "correct": false,
          "feedback": "Un fil n'est pas une copie du\nprogramme. Plusieurs fils partagent\nle même code et les mêmes données ;\nils peuvent tourner sur des cœurs\ndifférents sans dupliquer le\nprogramme.\n"
        },
        {
          "text": "Une fonction lancée automatiquement au démarrage du programme",
          "correct": false,
          "feedback": "Un fil n'est pas une fonction. C'est\nune unité d'exécution qui peut\nparcourir plusieurs fonctions, et on\nle lance explicitement : il ne\ndémarre pas tout seul.\n"
        }
      ],
      "explanation": "Une comparaison utile : un processus\nest comparable à une maison\nindépendante (sa mémoire est isolée),\ntandis qu'un fil d'exécution est\ncomparable à une pièce dans cette\nmaison (la mémoire reste partagée\navec les autres pièces)."
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "pid"
      ],
      "title": "Identifiant de processus",
      "statement": "Que désigne le **PID** d'un processus ?",
      "options": [
        {
          "text": "Un module interne du noyau spécialement chargé de créer et de gérer les processus",
          "correct": false,
          "feedback": "Cette interprétation est\nfantaisiste. Le sigle PID désigne\nsimplement un identifiant\nnumérique unique attribué par le\nsystème.\n"
        },
        {
          "text": "Un numéro unique attribué par le système à chaque processus pour l'identifier",
          "correct": true,
          "feedback": "Le PID, pour *Process IDentifier*,\npermet d'identifier les processus\nde manière unique. On l'utilise\npar exemple avec la commande\n`kill <PID>`. Sur les systèmes\nUnix, le numéro $1$ est\ntraditionnellement attribué au\nprocessus de démarrage.\n"
        },
        {
          "text": "Le descripteur des permissions et des droits d'accès d'un processus",
          "correct": false,
          "feedback": "Les permissions et le PID sont des\nnotions distinctes. Le PID\nidentifie un processus ; les\npermissions définissent ce que ce\nprocessus peut faire.\n"
        },
        {
          "text": "Un nom de domaine personnel réservé sur Internet",
          "correct": false,
          "feedback": "Aucun rapport avec les domaines\nInternet. Le PID est un numéro\ninterne au système d'exploitation.\n"
        }
      ],
      "explanation": "Sur les systèmes Unix, la commande\n`ps` affiche les PID en cours.\n`kill <PID>` envoie le signal\n`TERM` par défaut, et\n`kill -9 <PID>` envoie le signal\n`KILL`, qui est plus brutal et ne\npeut pas être ignoré par le\nprocessus visé."
    },
    {
      "id": "q04",
      "difficulty": 1,
      "skills": [
        "etat-processus"
      ],
      "title": "États d'un processus",
      "statement": "Quels sont les **états principaux** par\nlesquels passe un processus au cours de\nsa vie ?",
      "options": [
        {
          "text": "Démarré, en exécution et terminé, sans état d'attente intermédiaire",
          "correct": false,
          "feedback": "Ces états ne suffisent pas à\ndécrire le cycle de vie d'un\nprocessus : il manque l'état\n**bloqué**, où le processus attend\nune ressource ou une entrée-sortie.\n"
        },
        {
          "text": "Compilé, chargé en mémoire, puis exécuté par le processeur",
          "correct": false,
          "feedback": "Ce sont les étapes de fabrication\net de chargement d'un programme,\npas les états d'ordonnancement d'un\nprocessus en cours de vie.\n"
        },
        {
          "text": "Prêt, en exécution, bloqué en attente d'une ressource, puis terminé",
          "correct": true,
          "feedback": "C'est le modèle classique en\nsystème d'exploitation.\nL'ordonnanceur gère les\ntransitions entre l'état « prêt »\net l'état « en exécution ».\nL'état « bloqué » correspond à\nl'attente d'une ressource (un\nfichier, le réseau, un verrou).\n"
        },
        {
          "text": "Ouvert, modifié, puis enregistré et fermé par l'utilisateur du logiciel",
          "correct": false,
          "feedback": "Ce sont les états d'un **fichier**\nque l'on édite, pas ceux d'un\nprocessus géré par l'ordonnanceur.\n"
        }
      ],
      "explanation": "Sous Linux, la commande `ps -aux`\naffiche l'état de chaque processus :\n`R` pour *running* (en exécution),\n`S` pour *sleeping* (en sommeil),\n`D` pour *disk wait* (en attente\nd'entrée-sortie disque), `Z` pour\nzombie."
    },
    {
      "id": "q05",
      "difficulty": 1,
      "skills": [
        "ordonnanceur"
      ],
      "title": "Ordonnanceur",
      "statement": "Quel composant choisit **quel processus**\nreçoit le processeur à chaque instant ?",
      "options": [
        {
          "text": "L'interpréteur de commandes, qui lance les programmes depuis le terminal",
          "correct": false,
          "feedback": "L'interpréteur de commandes sert\nà lancer des programmes, mais ce\nn'est pas lui qui décide à quel\nmoment chaque processus reçoit le\nprocesseur.\n"
        },
        {
          "text": "Le pilote du processeur, qui dialogue avec le matériel",
          "correct": false,
          "feedback": "Un pilote est un module qui\npermet au système de communiquer\navec un périphérique matériel\n(carte réseau, imprimante, etc.).\nCe n'est pas son rôle de choisir\nquel processus s'exécute.\n"
        },
        {
          "text": "L'utilisateur, qui fixe l'ordre d'exécution à chaque instant",
          "correct": false,
          "feedback": "L'utilisateur peut influencer\nindirectement l'ordonnancement\n(en modifiant la priorité d'un\nprocessus, par exemple), mais il\nne décide pas à chaque instant\nquel processus reçoit le\nprocesseur.\n"
        },
        {
          "text": "L'ordonnanceur, un composant du noyau du système",
          "correct": true,
          "feedback": "L'ordonnanceur décide selon\nplusieurs critères : la priorité\ndu processus, l'équité globale\nentre les processus, la latence\nattendue. Sous Linux,\nl'ordonnanceur en place s'appelle\n*Completely Fair Scheduler*.\n"
        }
      ],
      "explanation": "Plusieurs stratégies d'ordonnancement\nexistent : le tour de rôle, la\npriorité statique ou dynamique, ou\nencore l'ordonnancement fondé sur la\nlatence. Pour les systèmes\nd'exploitation à contraintes temps\nréel, il faut des garanties strictes\nsur les délais d'exécution."
    },
    {
      "id": "q06",
      "difficulty": 1,
      "skills": [
        "parallelisme"
      ],
      "title": "Parallélisme et concurrence",
      "statement": "Quelle est la différence entre\n**parallélisme** et **concurrence** ?",
      "options": [
        {
          "text": "La concurrence alterne des tâches sur un cœur ; le parallélisme les exécute sur plusieurs cœurs à la fois",
          "correct": true,
          "feedback": "Avec un seul cœur, on peut être\nen concurrence (les tâches\nalternent), mais pas en\nparallélisme. Plusieurs cœurs\npermettent un véritable\nparallélisme.\n"
        },
        {
          "text": "Les deux termes sont synonymes : ils désignent l'exécution simultanée de plusieurs tâches",
          "correct": false,
          "feedback": "La distinction est au contraire\nessentielle : la concurrence peut\nexister sur un seul cœur (par\nalternance), alors que le\nparallélisme exige plusieurs cœurs.\n"
        },
        {
          "text": "La concurrence concerne les processus alors que le parallélisme concerne uniquement les fils d'exécution",
          "correct": false,
          "feedback": "La distinction ne porte pas sur\nprocessus contre fils : les deux\nnotions s'appliquent aussi bien aux\nuns qu'aux autres. Elle porte sur\nl'alternance contre la simultanéité\nréelle.\n"
        },
        {
          "text": "Le parallélisme accélère toujours un programme, contrairement à la concurrence",
          "correct": false,
          "feedback": "Cette affirmation est trop\nsimpliste. Le parallélisme peut\naccélérer un calcul, mais il\nintroduit un coût de\nsynchronisation et n'est pas\ntoujours bénéfique.\n"
        }
      ],
      "explanation": "Aujourd'hui, les processeurs\nmulti-cœurs offrent un véritable\nparallélisme. En Python, le module\n`multiprocessing` permet du\nparallélisme effectif, alors que le\nmodule `threading` n'offre que de\nla concurrence dans l'implémentation\nde référence du langage."
    },
    {
      "id": "q07",
      "difficulty": 1,
      "skills": [
        "memoire-partagee"
      ],
      "title": "Mémoire partagée entre fils d'exécution",
      "statement": "Pourquoi les fils d'exécution d'un même\nprocessus **partagent-ils** leur mémoire ?",
      "options": [
        {
          "text": "Pour échanger rapidement des données via des variables communes",
          "correct": true,
          "feedback": "C'est l'avantage majeur des fils\nd'exécution par rapport aux\nprocessus. Cette communication\nrapide est cependant source de\nbugs subtils si l'on ne\nsynchronise pas correctement les\naccès aux variables partagées.\n"
        },
        {
          "text": "Pour économiser des cœurs de processeur lors des calculs longs et intensifs",
          "correct": false,
          "feedback": "Le partage de la mémoire ne\npermet pas d'économiser des\ncœurs. Son intérêt principal\ntient à la rapidité de la\ncommunication entre fils\nd'exécution.\n"
        },
        {
          "text": "Parce que le noyau interdit aux fils d'avoir une mémoire séparée",
          "correct": false,
          "feedback": "Ce n'est pas une interdiction du\nnoyau : le partage est un choix de\nconception qui rend les fils légers\net rapides à faire communiquer.\n"
        },
        {
          "text": "Pour chiffrer automatiquement les données échangées entre eux",
          "correct": false,
          "feedback": "Le partage de mémoire n'a aucun\nrapport avec le chiffrement. Il\nvise la rapidité de communication,\npas la protection des données.\n"
        }
      ],
      "explanation": "C'est un compromis classique entre\nperformance et sécurité. Les fils\nd'exécution communiquent rapidement,\nmais leur partage de mémoire est\nrisqué. Les processus, à l'inverse,\nsont fortement isolés, mais leur\ncommunication est plus coûteuse."
    },
    {
      "id": "q08",
      "difficulty": 1,
      "skills": [
        "signal"
      ],
      "title": "Signal",
      "statement": "Qu'est-ce qu'un **signal** sous Unix ?",
      "options": [
        {
          "text": "Une notification asynchrone envoyée à un processus pour lui demander une action",
          "correct": true,
          "feedback": "Quelques signaux courants :\n`SIGTERM` (demande polie de\nterminaison), `SIGKILL`\n(terminaison brutale, qui ne\npeut pas être ignorée), `SIGINT`\n(interruption clavier, par\nexemple Ctrl+C), `SIGHUP`\n(rechargement de la\nconfiguration).\n"
        },
        {
          "text": "Une instruction particulière appartenant au jeu d'instructions câblé du processeur",
          "correct": false,
          "feedback": "Les signaux sont une notion du\nsystème d'exploitation, et non\ndu jeu d'instructions du\nprocesseur.\n"
        },
        {
          "text": "Un message texte échangé entre deux machines sur le réseau",
          "correct": false,
          "feedback": "Les signaux n'ont aucun rapport\navec les protocoles réseau ; ils\nsont locaux à un système\nd'exploitation.\n"
        },
        {
          "text": "Une variable globale partagée entre tous les processus",
          "correct": false,
          "feedback": "Un signal n'est pas une donnée\npartagée mais une notification : le\nnoyau interrompt le processus visé\npour lui transmettre une demande.\n"
        }
      ],
      "explanation": "La commande `kill -<signal> <PID>`\nenvoie un signal donné au processus\ndésigné. Par défaut, c'est\n`SIGTERM` (numéro $15$) qui est\nenvoyé. Le signal `SIGKILL`\n(numéro $9$) est plus brutal : le\nprocessus ne peut pas le bloquer ni\nle retarder."
    },
    {
      "id": "q09",
      "difficulty": 1,
      "skills": [
        "exemple-processus"
      ],
      "title": "Lister les processus",
      "statement": "Quelle commande Unix affiche la **liste des processus** en cours d'exécution ?",
      "options": [
        {
          "text": "`ps`, ou `top` pour un suivi en temps réel",
          "correct": true,
          "feedback": "On utilise par exemple `ps aux`\nou `ps -ef` pour obtenir la\nliste complète des processus.\nPour un suivi interactif et\ndynamique, on emploie plutôt\n`top` ou `htop`.\n"
        },
        {
          "text": "`ls`, qui liste le contenu d'un répertoire",
          "correct": false,
          "feedback": "La commande `ls` sert à lister\nle contenu d'un répertoire,\nc'est-à-dire les fichiers, pas\nles processus.\n"
        },
        {
          "text": "`cat`, qui affiche le contenu d'un fichier",
          "correct": false,
          "feedback": "La commande `cat` sert à\nafficher le contenu d'un\nfichier, et n'a aucun rapport\navec la liste des processus.\n"
        },
        {
          "text": "`grep`, qui recherche un motif dans un texte",
          "correct": false,
          "feedback": "La commande `grep` sert à\nrechercher un motif dans un\ntexte, mais pas à lister les\nprocessus en cours.\n"
        }
      ],
      "explanation": "Sous Windows, on peut utiliser le\nGestionnaire des tâches\n(`taskmgr.exe`) ou la commande\nPowerShell `Get-Process`. Quel\nque soit le système d'exploitation,\nla liste des processus est\nmaintenue par le noyau."
    },
    {
      "id": "q10",
      "difficulty": 1,
      "skills": [
        "demon"
      ],
      "title": "Démon",
      "statement": "Qu'appelle-t-on un **démon** sur un\nsystème d'exploitation ?",
      "options": [
        {
          "text": "Une commande Unix lancée manuellement par l'utilisateur depuis le terminal",
          "correct": false,
          "feedback": "Un démon n'est pas une commande\nmais un processus qui s'exécute\nen arrière-plan, généralement\nsans intervention de\nl'utilisateur.\n"
        },
        {
          "text": "Un programme malveillant qui se cache dans le système",
          "correct": false,
          "feedback": "Le mot « démon » est ici un\nterme technique sans connotation\nnégative. Il désigne un\nprocessus particulier, et non\nun logiciel malveillant.\n"
        },
        {
          "text": "Un processus d'arrière-plan, sans interface, qui rend un service au système",
          "correct": true,
          "feedback": "Les noms des démons se\nterminent souvent par la lettre\n« d » : `httpd`, `sshd`,\n`cron`, `systemd`. Ils sont\nvisibles avec la commande `ps`,\nmais aucun terminal ne leur est\nassocié.\n"
        },
        {
          "text": "Un fichier de configuration caché à la racine du système",
          "correct": false,
          "feedback": "Un démon est un processus, pas\nun fichier. Le mot « caché »\nrenvoie ici à l'absence\nd'interface utilisateur, pas à\nun fichier sur le disque.\n"
        }
      ],
      "explanation": "Sous Linux moderne, `systemd` est\nle processus de démarrage (PID 1)\net gère tous les autres démons.\nSous macOS, ce rôle revient à\n`launchd`. Sous Windows, on parle\nde « services Windows »."
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "course-critique"
      ],
      "title": "Course critique",
      "statement": "Qu'appelle-t-on une **course critique**\n(parfois nommée *race condition*) ?",
      "options": [
        {
          "text": "Une optimisation appliquée par le compilateur au moment de la traduction",
          "correct": false,
          "feedback": "Une course critique est un\ndéfaut de programmation, pas\nune optimisation. Elle survient\nà l'exécution, pas à la\ncompilation.\n"
        },
        {
          "text": "Un mécanisme de synchronisation chargé de protéger les données partagées entre fils",
          "correct": false,
          "feedback": "C'est l'inverse : une course\ncritique est le **problème** que\nla synchronisation (verrous,\nsémaphores) cherche justement à\néviter.\n"
        },
        {
          "text": "Un bug où l'ordre d'exécution de plusieurs fils rend le résultat imprévisible",
          "correct": true,
          "feedback": "Exemple typique : deux fils\nd'exécution incrémentent\nsimultanément la même variable.\nSelon l'entrelacement des\nopérations, le résultat varie.\nCes bugs sont particulièrement\ndifficiles à diagnostiquer car\nils sont souvent intermittents.\n"
        },
        {
          "text": "Une erreur qui ne concerne que les programmes à un seul fil d'exécution",
          "correct": false,
          "feedback": "C'est précisément l'inverse : une\ncourse critique suppose plusieurs\nfils accédant en même temps à des\ndonnées partagées. Un programme\nà un seul fil n'en produit pas.\n"
        }
      ],
      "explanation": "La solution consiste à mettre en\nplace une **synchronisation** des\naccès, par exemple à l'aide de\nverrous, de sémaphores, ou de\ntransactions atomiques. Une\nalternative consiste à éviter\ntoute donnée partagée, par exemple\nen utilisant un échange par files\nde messages."
    },
    {
      "id": "q12",
      "difficulty": 2,
      "skills": [
        "verrou"
      ],
      "title": "Verrou d'exclusion mutuelle",
      "statement": "À quoi sert un **verrou d'exclusion mutuelle** ?",
      "options": [
        {
          "text": "À stocker les données partagées entre plusieurs fils d'exécution",
          "correct": false,
          "feedback": "Un verrou ne stocke pas de\ndonnées, il contrôle l'accès à\ndes données stockées par\nailleurs.\n"
        },
        {
          "text": "À ralentir volontairement le programme pour économiser le processeur",
          "correct": false,
          "feedback": "Un verrou peut effectivement\nralentir le programme, mais ce\nn'est pas son objectif. Son\nrôle premier est de garantir la\ncohérence des données\npartagées.\n"
        },
        {
          "text": "À chiffrer les données partagées pour les protéger d'une lecture extérieure",
          "correct": false,
          "feedback": "Le chiffrement relève de la\ncryptographie, pas de la\nsynchronisation des fils\nd'exécution.\n"
        },
        {
          "text": "À garantir qu'un seul fil à la fois accède à une ressource partagée",
          "correct": true,
          "feedback": "Le motif classique est le\nsuivant : on acquiert le verrou,\non effectue les opérations\ncritiques, puis on libère le\nverrou. En Python, la syntaxe\n`with verrou:` garantit la\nlibération même en cas\nd'exception, ce qui est plus\nsûr.\n"
        }
      ],
      "explanation": "Plusieurs variantes existent : les\nsémaphores (qui généralisent le\nverrou avec un compteur), les\nverrous lecture-écriture (plusieurs\nlecteurs simultanés autorisés, mais\nun seul écrivain à la fois), et\nles moniteurs (par exemple en\nJava)."
    },
    {
      "id": "q13",
      "difficulty": 2,
      "skills": [
        "interblocage"
      ],
      "title": "Interblocage",
      "statement": "Qu'appelle-t-on un **interblocage** ?",
      "options": [
        {
          "text": "Un arrêt brutal et immédiat de l'ensemble du programme, déclenché par le noyau",
          "correct": false,
          "feedback": "Un interblocage n'est pas un\narrêt brutal : les processus\nimpliqués restent actifs, mais\nils sont bloqués en attente\nmutuelle. Aucun ne s'arrête de\nlui-même.\n"
        },
        {
          "text": "Un signal d'erreur particulier émis automatiquement par le système",
          "correct": false,
          "feedback": "L'interblocage n'émet pas de\nsignal particulier. Au\ncontraire, il se manifeste par\nun blocage silencieux que le\nprogrammeur doit détecter\nlui-même.\n"
        },
        {
          "text": "Un gel de l'affichage de l'écran le temps d'un calcul lourd",
          "correct": false,
          "feedback": "Le mot peut faire penser à un\ngel de l'affichage, mais le\nsens technique en informatique\nest tout autre. Il s'agit d'un\nblocage logique entre\nprocessus.\n"
        },
        {
          "text": "Une situation où plusieurs processus s'attendent mutuellement sans fin",
          "correct": true,
          "feedback": "Exemple : le fil $T_1$ détient\nla ressource $A$ et attend $B$.\nLe fil $T_2$ détient $B$ et\nattend $A$. Aucun ne peut\nprogresser. Quatre conditions,\ndites de Coffman, doivent être\nréunies simultanément pour\nqu'un interblocage se produise.\n"
        }
      ],
      "explanation": "Plusieurs stratégies de prévention\nexistent : ordonner systématiquement\nles acquisitions de ressources\n(toujours $A$ puis $B$),\nutiliser des délais d'attente\n(*timeouts*), détecter les\ninterblocages a posteriori (par\nanalyse des graphes d'attente), ou\nles éviter avec des algorithmes\ndédiés comme l'algorithme du\nbanquier de Dijkstra."
    },
    {
      "id": "q14",
      "difficulty": 2,
      "skills": [
        "ipc"
      ],
      "title": "Communication entre processus",
      "statement": "Comment deux processus **isolés**\npeuvent-ils communiquer entre eux ?",
      "options": [
        {
          "text": "Uniquement par des saisies successives au clavier de l'utilisateur",
          "correct": false,
          "feedback": "Le clavier permet à un\nutilisateur d'interagir avec\nun programme, mais ce n'est\npas un mécanisme de\ncommunication entre processus.\n"
        },
        {
          "text": "Uniquement via Internet, en passant par un serveur distant",
          "correct": false,
          "feedback": "Internet permet bien la\ncommunication entre processus\ndistants, mais ce n'est pas le\nseul mécanisme. De nombreux\nprocessus communiquent\nlocalement, sans passer par\nInternet.\n"
        },
        {
          "text": "Par des tubes, des sockets, des fichiers partagés ou des files de messages",
          "correct": true,
          "feedback": "Tous ces mécanismes sont\nfournis par le système\nd'exploitation. Le tube Unix,\nsymbolisé par la barre\nverticale `|` dans\nl'interpréteur de commandes,\nest l'un des plus simples\nd'usage. Les sockets servent\naux communications réseau, et\nla mémoire partagée privilégie\nla performance.\n"
        },
        {
          "text": "C'est impossible : deux processus isolés ne peuvent jamais communiquer",
          "correct": false,
          "feedback": "Plusieurs mécanismes\npermettent au contraire à des\nprocessus isolés de\ncommuniquer (tubes, sockets,\nfichiers, files de messages).\n"
        }
      ],
      "explanation": "Le choix du mécanisme dépend du\nbesoin : un tube convient pour un\nsimple flux ; une connexion\nréseau, pour communiquer à\ndistance ; la mémoire partagée,\npour la performance ; une file de\nmessages, pour découpler le\nproducteur du consommateur."
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "creation-processus"
      ],
      "title": "Création d'un processus",
      "statement": "Sur les systèmes Unix, l'appel système\n`fork` permet de :",
      "options": [
        {
          "text": "Remplacer le programme courant par un nouveau programme à exécuter",
          "correct": false,
          "feedback": "Cette opération correspond à\nl'appel système `exec`, qui\nest souvent combiné avec\n`fork` pour lancer un nouveau\nprogramme dans un nouveau\nprocessus.\n"
        },
        {
          "text": "Arrêter immédiatement le processus appelant et libérer sa mémoire",
          "correct": false,
          "feedback": "La terminaison d'un processus\nse fait avec un appel système\ncomme `exit`, et non avec\n`fork`.\n"
        },
        {
          "text": "Dupliquer le processus appelant en un parent et un enfant",
          "correct": true,
          "feedback": "Après l'appel à `fork`, on\ndistingue le parent et l'enfant\npar la valeur renvoyée : la\nfonction renvoie $0$ dans le\nprocessus enfant, et le\nnuméro de l'enfant dans le\nprocessus parent. Ce mécanisme\nest fondamental sous Unix.\n"
        },
        {
          "text": "Créer un nouveau fichier vide sur le disque pour le processus",
          "correct": false,
          "feedback": "La création d'un fichier\nrelève d'autres appels\nsystème, comme `open` avec\nl'option de création. L'appel\n`fork` concerne les processus,\npas les fichiers.\n"
        }
      ],
      "explanation": "Le motif classique sous Unix est\nl'enchaînement `fork` puis `exec` :\non duplique le processus, puis on\nremplace l'image mémoire de\nl'enfant par un autre programme.\nLe parent peut ensuite continuer\nen parallèle ou attendre la fin\nde l'enfant avec un appel à\n`wait`."
    },
    {
      "id": "q16",
      "difficulty": 2,
      "skills": [
        "zombie"
      ],
      "title": "Processus zombie",
      "statement": "Qu'appelle-t-on un **processus zombie** ?",
      "options": [
        {
          "text": "Un processus terminé dont le parent n'a pas encore lu le code de retour",
          "correct": true,
          "feedback": "Cet état apparaît avec la\nlettre `Z` dans la commande\n`ps`. Il est normalement\néphémère. Une accumulation de\nprocessus zombies traduit\nsouvent un bug : le parent ne\nrécupère pas le statut de ses\nenfants. Si le parent meurt,\nle processus de démarrage\n(PID 1) « adopte » les\nprocessus orphelins.\n"
        },
        {
          "text": "Un processus dangereux qui menace la stabilité du système",
          "correct": false,
          "feedback": "Le mot « zombie » est ici un\nterme technique sans\nconnotation négative. Il\ndésigne un état particulier\ndans le cycle de vie d'un\nprocessus.\n"
        },
        {
          "text": "Un signal système particulier envoyé à un processus mourant",
          "correct": false,
          "feedback": "Le zombie n'est pas un signal\nmais un état d'un processus :\ncelui d'un processus terminé en\nattente de récupération.\n"
        },
        {
          "text": "Un processus bloqué dans une boucle infinie qui sature en continu le processeur",
          "correct": false,
          "feedback": "Une boucle infinie correspond\nà un processus qui consomme du\ntemps processeur sans\nterminer. Le zombie est un\nprocessus déjà terminé, dont\nil reste seulement l'entrée\ndans la table des processus.\n"
        }
      ],
      "explanation": "Pour éviter l'apparition de\nprocessus zombies, le parent doit\nappeler `wait` ou `waitpid` après\nla création d'un processus\nenfant. Sans cela, le processus\nenfant reste dans l'état zombie\njusqu'à ce que le parent le\nrécupère explicitement."
    },
    {
      "id": "q18",
      "difficulty": 2,
      "skills": [
        "priorite"
      ],
      "title": "Priorité d'un processus",
      "statement": "Pourquoi un système d'exploitation\nattribue-t-il des **priorités**\ndifférentes aux processus ?",
      "options": [
        {
          "text": "Pour donner plus de temps processeur aux processus les plus importants",
          "correct": true,
          "feedback": "Une priorité élevée signifie\nplus de temps processeur\nalloué. Sous Linux, la\ncommande `nice` permet de\nrégler cette priorité (de\n$-20$ à $19$ ; un nombre plus\ngrand signifie un processus\nplus « gentil », c'est-à-dire\nmoins prioritaire).\n"
        },
        {
          "text": "Pour renforcer la sécurité en isolant les processus les uns des autres",
          "correct": false,
          "feedback": "La sécurité est gérée par les\npermissions et les\nmécanismes d'isolation, pas\npar les priorités, qui\nconcernent l'allocation du\ntemps processeur.\n"
        },
        {
          "text": "Pour réserver une quantité de mémoire vive fixe à chaque processus",
          "correct": false,
          "feedback": "La priorité ne fixe pas la\nmémoire allouée : elle agit sur\nle partage du temps processeur,\npas sur celui de la mémoire.\n"
        },
        {
          "text": "Pour respecter l'ordre exact dans lequel les programmes ont été lancés",
          "correct": false,
          "feedback": "L'ordre de lancement ne\ndétermine pas la priorité : un\nprocessus lancé tardivement peut\nêtre plus prioritaire qu'un\nautre lancé avant lui.\n"
        }
      ],
      "explanation": "Les systèmes d'exploitation à\ncontraintes temps réel offrent\ndes garanties strictes sur la\npriorité. Les systèmes\ngénéralistes adoptent une\npolitique « au mieux », tout en\ncherchant à maintenir une équité\nglobale entre les processus."
    },
    {
      "id": "q19",
      "difficulty": 2,
      "skills": [
        "exemples-windows"
      ],
      "title": "Lister les processus sous Windows",
      "statement": "Comment afficher les processus actifs\nsur **Windows** ?",
      "options": [
        {
          "text": "Avec le Gestionnaire des tâches, ou la commande PowerShell `Get-Process`",
          "correct": true,
          "feedback": "Le Gestionnaire des tâches\n(raccourci Ctrl + Maj + Échap)\noffre une interface graphique\nriche. En ligne de commande,\non dispose de `tasklist`\n(commande historique) ou de\n`Get-Process` dans\nPowerShell.\n"
        },
        {
          "text": "Avec la commande `ps`, comme sur les systèmes Unix",
          "correct": false,
          "feedback": "La commande `ps` est propre\naux systèmes Unix. Elle n'est\npas disponible nativement\nsous Windows.\n"
        },
        {
          "text": "C'est impossible : Windows masque ses processus à l'utilisateur",
          "correct": false,
          "feedback": "Plusieurs outils permettent\nau contraire d'observer les\nprocessus (Gestionnaire des\ntâches, `tasklist`,\n`Get-Process`).\n"
        },
        {
          "text": "En redémarrant complètement Windows pour afficher la liste au prochain démarrage",
          "correct": false,
          "feedback": "Redémarrer le système ne permet\npas d'observer les processus en\ncours : il faut au contraire un\noutil de supervision sur un\nsystème en fonctionnement.\n"
        }
      ],
      "explanation": "Sur tous les systèmes\nd'exploitation modernes, on peut\nobserver les processus, mesurer\nleur consommation de ressources\net les terminer. Les outils\ndiffèrent, mais les fonctions\nproposées sont équivalentes."
    },
    {
      "id": "q21",
      "difficulty": 3,
      "skills": [
        "coffman"
      ],
      "title": "Conditions nécessaires à un interblocage",
      "statement": "Quelles sont les **quatre conditions nécessaires** pour qu'un interblocage\npuisse se produire (selon Coffman,\n$1971$) ?",
      "options": [
        {
          "text": "La mémoire, le processeur, le disque et le réseau",
          "correct": false,
          "feedback": "Ces éléments sont des types\nde ressources, mais ils ne\nconstituent pas les\nconditions de Coffman, qui\ndécrivent une situation\nd'attente entre processus.\n"
        },
        {
          "text": "La compilation, l'édition de liens, puis le chargement en mémoire et l'exécution finale du programme",
          "correct": false,
          "feedback": "Ce sont les étapes de\nfabrication d'un programme,\nsans rapport avec les\nconditions d'apparition d'un\ninterblocage entre processus.\n"
        },
        {
          "text": "L'exclusion mutuelle, la détention et l'attente, la non-préemption et l'attente circulaire",
          "correct": true,
          "feedback": "Casser une seule de ces\nconditions suffit à éliminer\nle risque d'interblocage.\nPlusieurs stratégies sont\npossibles : autoriser la\npréemption (ce qui casse la\ntroisième condition), ou\nordonner globalement\nl'acquisition des ressources\n(ce qui casse la quatrième).\n"
        },
        {
          "text": "La priorité, l'équité, la latence et le quantum de temps",
          "correct": false,
          "feedback": "Ce sont des critères\nd'ordonnancement, et non les\nconditions de Coffman qui\ncaractérisent une situation\nd'interblocage.\n"
        }
      ],
      "explanation": "Cette théorie classique permet\nd'analyser tout système\nconcurrent et constitue un\ncontenu classique des cours sur\nles systèmes d'exploitation."
    },
    {
      "id": "q25",
      "difficulty": 3,
      "skills": [
        "synthese"
      ],
      "title": "Synthèse",
      "statement": "Parmi les affirmations suivantes sur\nles processus et les fils d'exécution,\nlaquelle est **fausse** ?",
      "options": [
        {
          "text": "Plusieurs fils d'exécution d'un même processus partagent la mémoire",
          "correct": false,
          "feedback": "Cette affirmation est\ncorrecte. C'est même la\ncaractéristique majeure des\nfils d'exécution.\n"
        },
        {
          "text": "Un interblocage requiert la conjonction simultanée des quatre conditions de Coffman",
          "correct": false,
          "feedback": "Cette affirmation est\ncorrecte. Casser l'une de\nces quatre conditions suffit\nà éviter l'interblocage.\n"
        },
        {
          "text": "Une course critique est résolue automatiquement par le système d'exploitation",
          "correct": true,
          "feedback": "Cette affirmation est fausse\n(donc c'est la bonne\nréponse). Le système\nd'exploitation ne résout pas\nles courses critiques. Il\nrevient au programmeur\nd'utiliser des mécanismes de\nsynchronisation appropriés\n(verrous, sémaphores, files\nsynchronisées) pour les\néviter.\n"
        },
        {
          "text": "Un processus dispose de sa propre mémoire isolée des autres processus",
          "correct": false,
          "feedback": "Cette affirmation est\ncorrecte. L'isolation de la\nmémoire est précisément ce\nqui distingue les processus\ndes fils d'exécution.\n"
        }
      ],
      "explanation": "Le programmeur reste\nresponsable de la correction de\nson code concurrent. Le système\nd'exploitation fournit les\noutils, mais c'est à\nl'application d'en faire un\nusage rigoureux pour garantir la\ncohérence des données\npartagées."
    },
    {
      "id": "q26",
      "difficulty": 2,
      "skills": [
        "appel-systeme"
      ],
      "title": "Appel système",
      "statement": "Qu'appelle-t-on un **appel système**\n(*system call*) ?",
      "options": [
        {
          "text": "Une fonction interne au programme utilisateur, exécutée sans quitter son espace",
          "correct": false,
          "feedback": "Erreur : un appel système n'est\npas une fonction interne au\nprogramme. C'est précisément un\nmécanisme par lequel le programme\nsort de son espace propre pour\ndemander un service au noyau.\n"
        },
        {
          "text": "Un appel téléphonique automatisé passé par le système d'exploitation",
          "correct": false,
          "feedback": "Erreur : ce terme n'a aucun\nrapport avec la téléphonie. Il\ndésigne un mécanisme interne du\nsystème d'exploitation.\n"
        },
        {
          "text": "Un protocole de communication réseau entre deux machines distantes",
          "correct": false,
          "feedback": "Erreur : un appel système est\nlocal au système d'exploitation\nd'une machine. La communication\nréseau peut **passer par** des\nappels système (par exemple\n`socket`), mais elle n'est pas\nelle-même un appel système.\n"
        },
        {
          "text": "Une demande de service adressée par un programme au noyau du système",
          "correct": true,
          "feedback": "Bonne réponse : les appels\nsystème sont l'interface entre le\nmode utilisateur (où s'exécutent\nles programmes ordinaires) et le\nmode noyau (où s'exécutent les\nopérations privilégiées). Un\nappel système provoque un\nchangement de contexte vers le\nnoyau, qui exécute la requête\npuis rend la main au programme.\nExemples : `open`, `read`,\n`write`, `fork`, `exec`.\n"
        }
      ],
      "explanation": "Sous Linux, on peut observer les\nappels système d'un programme avec\n`strace`. Les appels système sont\ncoûteux car ils provoquent un\nchangement de contexte. Les\nbibliothèques standard les\nregroupent souvent (par exemple,\nbufferisation des écritures) pour\nréduire leur nombre."
    },
    {
      "id": "q27",
      "difficulty": 3,
      "skills": [
        "memoire-virtuelle"
      ],
      "title": "Mémoire virtuelle",
      "statement": "Pourquoi les systèmes d'exploitation\nmodernes utilisent-ils la **mémoire virtuelle** pour les processus ?",
      "options": [
        {
          "text": "Pour réduire la consommation électrique de la mémoire vive au repos",
          "correct": false,
          "feedback": "Erreur : la mémoire virtuelle\nn'a pas pour objectif principal\nla réduction de la consommation\nélectrique. Son rôle premier\nest l'isolation et la flexibilité\nde gestion mémoire.\n"
        },
        {
          "text": "Parce que la mémoire physique n'existe tout simplement plus dans les ordinateurs récents",
          "correct": false,
          "feedback": "Erreur : la mémoire physique\nexiste bel et bien dans tout\nordinateur ; c'est elle qui\nstocke les données réellement.\nLa mémoire virtuelle est une\nabstraction logicielle au-dessus\nde la mémoire physique.\n"
        },
        {
          "text": "Pour donner à chaque processus un espace privé et l'isoler des autres",
          "correct": true,
          "feedback": "Bonne réponse : la mémoire\nvirtuelle est l'un des piliers\ndes systèmes d'exploitation\nmodernes. Avantages : isolation\n(un processus ne peut pas écrire\ndans la mémoire d'un autre),\nflexibilité (la mémoire physique\npeut être fragmentée), illusion\nd'abondance (le système peut\ndéborder sur le disque dur via\nle swap). Inconvénient : un\nléger surcoût lié à la\ntraduction d'adresses, mitigé\npar des composants matériels\ndédiés (TLB).\n"
        },
        {
          "text": "Pour rendre l'écriture des programmes plus rapide pour les développeurs",
          "correct": false,
          "feedback": "Erreur : la mémoire virtuelle\nn'a pas d'effet direct sur la\nrapidité de développement.\nElle simplifie certains\naspects, mais ce n'est pas son\nmotif principal.\n"
        }
      ],
      "explanation": "Sans mémoire virtuelle, un processus\npourrait lire ou écrire dans la\nmémoire d'un autre processus, ce\nqui poserait des problèmes de\nsécurité majeurs. Aussi, les\nadresses utilisées dans le code\nseraient liées à la position\neffective en mémoire, ce qui\ncompliquerait fortement la\ncompilation et le chargement de\nprogrammes."
    },
    {
      "id": "q22",
      "difficulty": 3,
      "skills": [
        "synthese",
        "interblocage",
        "coffman"
      ],
      "title": "Reconnaître un interblocage",
      "statement": "Deux processus $P_1$ et $P_2$ utilisent deux\nressources $A$ et $B$ que le système d'exploitation\nn'autorise qu'à un seul processus à la fois (ressources\nnon préemptibles). À un instant donné, $P_1$ détient\n$A$ et attend $B$, pendant que $P_2$ détient $B$ et\nattend $A$. Aucun des deux ne lâchera la ressource\nqu'il détient. Quelle situation s'est produite ?",
      "options": [
        {
          "text": "Un interblocage, car les quatre conditions de Coffman sont toutes réunies",
          "correct": true,
          "feedback": "Bonne réponse : l'interblocage (en anglais\n*deadlock*) se reconnaît à la coexistence des\nquatre conditions de Coffman. Ici elles sont toutes\nprésentes : les ressources sont exclusives, chaque\nprocessus tient une ressource tout en en demandant\nune autre, le système ne peut pas retirer les\nressources de force, et la chaîne d'attente forme\nun cycle.\n"
        },
        {
          "text": "Une famine, car l'un des deux processus n'obtient jamais sa ressource",
          "correct": false,
          "feedback": "Erreur : la famine concerne un processus qui\nn'obtient jamais une ressource demandée parce que\nd'autres lui passent systématiquement devant.\nDans le cas présent, les **deux** processus sont\nbloqués mutuellement.\n"
        },
        {
          "text": "Une situation de compétition, car les deux processus s'exécutent en concurrence",
          "correct": false,
          "feedback": "Erreur : une situation de compétition désigne un\ncomportement dont le résultat dépend de l'ordre\nd'exécution non maîtrisé entre processus. Ici, le\ncomportement est parfaitement reproductible et\ndéterministe : tout est figé.\n"
        },
        {
          "text": "Une file d'attente normale du système, sans problème particulier",
          "correct": false,
          "feedback": "Erreur : dans une file d'attente normale, les\nprocessus progressent à tour de rôle. Ici, aucun\ndes deux n'avance et aucun n'avancera, c'est tout\nsauf normal.\n"
        }
      ],
      "explanation": "L'interblocage se résout en cassant au moins l'une des\nquatre conditions de Coffman, par exemple en imposant\nun ordre total d'acquisition des ressources (ce qui\ncasse la condition de cycle), ou en autorisant le\nsystème à retirer une ressource d'un processus (ce\nqui casse la non-préemption). Les bases de données et\nles systèmes d'exploitation détectent activement ce\ntype de situation."
    },
    {
      "id": "q23",
      "difficulty": 3,
      "skills": [
        "synthese",
        "etats",
        "ordonnancement"
      ],
      "title": "Comprendre l'état bloqué",
      "statement": "Sur un ordinateur en fonctionnement, un processus est\nobservé dans l'état « **en attente** » (ou « bloqué »)\ndepuis plusieurs secondes. Que peut-on en déduire de\nplus probable ?",
      "options": [
        {
          "text": "Il attend un événement extérieur ; l'ordonnanceur a donné le processeur à d'autres",
          "correct": true,
          "feedback": "Bonne réponse : l'état « en attente » signale que le\nprocessus ne peut pas progresser parce qu'il attend\nun événement extérieur (saisie clavier, lecture\ndisque, réception réseau, libération d'une\nressource). L'ordonnanceur ne lui alloue pas le\nprocesseur pendant ce temps : il attribue les\ncycles à des processus qui sont, eux, à l'état\n« prêt ».\n"
        },
        {
          "text": "Il utilise activement le processeur pour effectuer un calcul intensif",
          "correct": false,
          "feedback": "Erreur : un processus qui utilise le processeur est\ndans l'état « élu » (ou « en exécution »), pas dans\nl'état « en attente ».\n"
        },
        {
          "text": "Il consomme une grande quantité de mémoire vive sur la machine",
          "correct": false,
          "feedback": "Erreur : la consommation de mémoire n'a aucun\nrapport avec l'état d'ordonnancement du processus.\nUn processus en attente peut détenir beaucoup ou\npeu de mémoire.\n"
        },
        {
          "text": "Il a planté et le système d'exploitation s'apprête à le supprimer",
          "correct": false,
          "feedback": "Erreur : un processus planté passe à l'état\n« terminé ». L'état « en attente » est, lui, un\nétat tout à fait normal dans le cycle de vie d'un\nprocessus.\n"
        }
      ],
      "explanation": "Un processus typique alterne plusieurs fois entre les\nétats « prêt », « élu » et « en attente » au cours de\nsa vie. C'est ce qui rend la multiprogrammation\nefficace : pendant qu'un processus attend une lecture\nlente sur disque, l'ordonnanceur donne le processeur à\nun autre qui a du travail à faire. La transition entre\nétats est entièrement gérée par le noyau."
    }
  ]
}