Bref – unités d'exécution

Le nom le dit : ceci n'est qu'un bref, pas une description exhaustive du sujet.

Ce qui suit décrit très brièvement les principaux types d'unités d'exécution mis à notre disposition par un système d'exploitation, soit les processus, les threads et les fibres.

Processus

On peut faire des comparaisons entre processus et objets (états, méthodes, isolation entre les processus). Voir le système d'exploitation comme unité d'organisation des processus, tout comme le processus peut servir d'unité d'organisation entre les objets.

Un processus est la contrepartie dynamique d'un programme : il est en exécution, avec ses données et ses ressources. On peut donc avoir plusieurs processus pour un même programme, chacun avec ses propres états.

Un changement de contexte se produira typiquement lors d'un appel système, lors d'une entrée/ sortie ou lors d'une interruption matérielle, et impliquera de conserver le contexte du processus actif avant le changement puis de récupérer et de remettre en place le contexte du processus qui sera actif après le changement.

Un processus occupe son espace adressable. Cet espace contient essentiellement un segment de code, un segment de données et au moins un segment de pile. On peut ajouter les ressources du système d'exploitation qui lui sont confiées, les considérations de sécurité (identité de l'usager exécutant, ACL) et, de manière indirecte, l'état du contexte (l'état des registres du processeur).

Un processus a typiquement un point d'entrée (en C et en C++ : main()), qui constitue le lieu d'où démarre son exécution. Les processus sont typiquement isolés mutuellement les uns des autres, ce qui explique qu'on leur offre des mécanismes de communication (sockets, tuyaux, fichiers, mémoire partagée, file de messages, etc.).

On parle d'ordonnancement préemptif quand un thread ou un processus en cours d'exécution peut se faire remplacer par un autre au gré de l'ordonnanceur (le module qui décide à qui le tour de s'exécuter).

Dans un système à ordonnancement non-préemptif (ou collaboratif, comme on dit parfois), le thread qui s'exécute poursuit tant qu'il ne donne pas explicitement sa place à un autre.

En pratique, il y a de la place pour les deux modèles

Le système d'exploitation ordonnance les processus, donc détermine quel processus s'exécutera parmi ceux qui le pourraient. L'ordonnancement sur un système d'exploitation contemporain impliquera typiquement du temps partagé ou de la concurrence. Il pourra être préemptif (Win95+, Linux) ou non préemptif, parfois appelé « préemptif collaboratif » (Win 3.11, plusieurs SETR).

Un processeur n'opère qu'une instruction à la fois (bien qu'il y ait des micro-instructions, nous y reviendrons). Le temps partagé est d'ailleurs né de l'idée de partager cette ressource qu'est le processeur; sur un ordinateur monoprocesseur, un seul processus s'exécute à la fois, et si l'un d'eux bloque...

Thread

Les threads, ou fils d'exécution concurrents, peuvent être vus comme une réévaluation de l'idée de processus : un segment de code, un segment de données, au moins un segment de pile, au moins un contexte d'exécution, et ainsi de suite pour les considérations indirectes (la sécurité peut être par thread, ou par processus, ou les deux, selon les plateformes et les technologies), et parfois de la mémoire locale par thread.

Un processus comprend au moins un thread, soit le thread principal, là d'où démarre l'exécution du processus, et peut se séparer en plusieurs threads s'exécutant concurremment à partir de ce point.

Le changement de contexte est plus rapide et plus léger entre deux threads d'un même processus qu'entre deux threads de deux processus distincts. Deux threads d'un même processus en partagent les ressources globales, incluant l'espace adressable.

Les threads sont plus légers que les processus, mais sont aussi plus risqués : risques conditions de course, de décohésion due à des accès concurrents, d'interblocage (quoique les processus ne soient pas invulnérables à ceux-ci), etc.

Un programme découpé en threads tend à être plus facile à paralléliser sur plusieurs coeurs, une bonne partie du travail étant déjà faite.

Saveurs de threads

Il est possible pour un thread d'être pris en charge dans l'espace usager (User Space), et certains systèmes d'exploitation le supportent, mais les changements de contexte sont typiquement sous la responsabilité du système d'exploitation, et les threads sont donc dans l'espace du noyau (Kernel Space).

Pour quelques explications, voir http://tldp.org/FAQ/Threads-FAQ/Types.html ou encore cet article d'Andrew Tanenbaum en 2002 : http://www.informit.com/articles/article.aspx?p=25075

Une autre saveur particulière de thread est ce qu'on nomme les Green Threads. Ceux-ci sont gérés par une machine virtuelle, donc sont une « sous-saveur » des threads pris en charge par l'espace usager. Ils sont ordonnancées non pas par le système d'exploitation mais bien par la machine virtuelle, à l'insu du système d'exploitation.

Dans un système utilisant des Green Threads, les entrées/ sorties sont souvent asynchrones, de manière à ce qu'un Green Thread bloquant sur une entrée, par exemple, ne fige un processus tout entier.

Thread-Safety

Ce que signifie être Thread-Safe (en gros : être tel qu'on peut être utilisé de manière concurrente à partir de plusieurs threads) : http://en.wikipedia.org/wiki/Thread_safety

Être Thread-Safe avec C++ :

Être Thread-Safe avec Java :

Le Thread-Safety, d'un point de vue .NET, selon Eric Lippert :

Protothreads

Un Wiki sur le sujet : http://en.wikipedia.org/wiki/Protothreads

Comparer les protothreads et les automates : http://embeddedgurus.com/state-space/2011/06/protothreads-versus-state-machines/

Utiliser des protothreads pour lire des capteurs, texte de 2005 par Adam Dunkels, Oliver Schmidt et Thiemo Voigt : http://compilers.cs.ucla.edu/emsoft05/DunkelsSchmidtVoigt05.pdf

Threads ou processus?

Avec l'arrivée de Google Chrome et de Internet Explorer 8, deux fureteurs qui (par défaut) lancent un processus à part entière dans chaque onglet, alors que les habitudes des dernières années étaient de mettre l'accent sur la multiprogrammation à l'aide de plusieurs threads, plusieurs se questionnent sur les mérites relatifs de ces deux approches à la multiprogrammation. Pour lire sur le sujet :

Plusieurs coeurs signifie-t-il plusieurs threads? À ce sujet :

Sous Microsoft Windows, non seulement y a-t-il des threads mais il y a aussi des Threading Models. À ce sujet :

En 2014, Aaron Seigo prend position à l'effet que les architectures multi-processus seraient... Inadéquates? http://aseigo.blogspot.ca/2014/07/multi-process-architectures-suck.html

Fibre

Les fibres sont un mécanisme encore plus léger que les threads, et permettent une exécution multitâche coopérative à l'intérieur d'un processus. En effet, avec des fibres, un changement de contexte ne se fait que lorsqu'une fibre cède la main (yield). On parlera aussi de coroutines dans certains milieux.

Les fibres sont idéales quand un processus est en mesure de bien se gérer lui-même. Il s'agit du modèle préconisé par OpenMP, entre autres.

En résumé

Processus → Thread noyau → Thread usager → Fibre

Allant de gauche à droite :

Un processus peut bloquer sans interrompre l'exécution des autres, et il en va de même pour un thread géré par le noyau. Les threads gérés dans l'espace usager et les fibres sont tous deux des mécanismes collaboratifs, donc si l'un deux bloque, l'ensemble bloque. Ce sont donc des mécanismes pour lesquels les entrées/ sorties sont habituellement non-bloquantes.

Pour décrire la correspondance entre la réalité logique des programmes et la réalité plus concrète des outils offerts par le système d'exploitation ou le matériel, on trouve :

Lectures complémentaires

Divers textes sur le sujet :

Textes d'ordre général :

À propos de l'API standard de threads de C++ 11 :

À propos de l'optimisation de l'architecture Bulldozer, de la firme AMD : http://techreport.com/articles.x/21865

Les threads avec Java :

Les threads sous .NET :

Les threads de Microsoft Windows :

Les pthreads, ou threads POSIX :

À propos des processus :

À propos des fibres :


Valid XHTML 1.0 Transitional

CSS Valide !