L'ordonnanceur du noyau fait attention à séparer les processus dans le temps. Votre système d'exploitation les divise aussi dans l'espace, de telle manière que ces processus n'empiètent pas sur la mémoire de travail des autres. Ces choses que votre système d'exploitation réalise sont appelées gestion de la mémoire.
Chaque processus de votre 'troupeau' a besoin de son propre espace mémoire afin de mettre son code et de garder des variables et leur résultat. Vous pouvez imaginer cet ensemble constitué d'un segment de code accessible en lecture uniquement (contenant les instrucions du processus) et un segment de données accessible en écriture (contenant toutes les variables du processus). Le segment de données est véritablement propre à chaque processus, mais si deux processus exécutent le même code, Unix s'arrange automatiquement pour qu'ils partagent le même segment de code dans un soucis d'efficacité.
L'efficacité est importante car la mémoire est chère. Quelquefois, vous ne disposez pas de suffisamment de mémoire pour faire tenir tous les programmes, spécialement si vous utilisez un gros programme comme un serveur X-WINDOW. Pour contourner cela, Unix utilise une stratégie appelée mémoire virtuelle. Cela n'essaie pas de faire tenir tout le code et les données d'un processus en mémoire. Cependant, il garde seulement un espace de travail ; le reste de l'état du processus est laissé dans un endroit spécial sur votre disque : l'espace d'échange (swap space).
Lorsque le processus s'exécute, Unix essaie d'anticiper comment l' espace de travail changera, et ne chargera en mémoire que les morceaux dont il a besoin. Faire cela efficacement est compliqué et délicat, je n'essaierai pas de le décrire ici -- mais cela dépend du fait que le code et les références aux données peuvent arriver en blocs, avec chaque nouveau référençant vraisemblablement un proche ou un ancien. Ainsi, si Unix garde le code ou les données fréquemment (ou récemment) utilisés, vous gagnerez du temps.
Notez que dans le passé, le "quelquefois" que nous employons deux paragraphes plus haut était "souvent" voire "toujours", -- la taille de la mémoire était habituellement petite par rapport à la taille des programmes en cours d'exécution, de telle manière que les échanges entre le disque et la mémoire ("swapping") étaient fréquents. La mémoire est beaucoup moins chère de nos jours et même les machines bas de gamme en sont bien dotées. Sur les machines mono-utilisateur avec 64Mo de mémoire, il est possible de faire tourner X-WINDOW et un mélange de programmes sans jamais swapper.
Même dans cette situation joyeuse, la part du système d'exploitation appelée le gestionnaire de mémoire a un important travail à faire. Il doit être sûr que les programmes ne peuvent modifier que leurs segments de mémoire -- ce qui empêche un code erroné ou malicieux dans un programme de ramasser les données dans un autre. Pour faire cela, il conserve une table des segments de données et de code. La table est mise à jour chaque fois qu'un processus demande de la mémoire ou en libère (habituellement plus tard lorsqu'il se termine).
Cette table est utilisée pour passer des commandes à une partie spécialisée du matériel sous-jacent appelée un UGM (MMU) ou unité de gestion mémoire (memory management unit). Les processeurs modernes disposent de MMUs intégrés. Le MMU a la faculté de mettre des barrières autour de zones mémoire, ainsi une référence en "dehors des clous" sera refusée et générera une interruption spéciale pour être traitée.
Si vous avez déjà vu le message Unix qui dit "Segmentation fault", "core dumped" ou quelque chose de similaire, c'est exactement ce qu'il se passe ; un programme en cours d'exécution a tenté d'accéder à de la mémoire en dehors de son segment et a provoqué une interruption fatale. Cela indique un bug dans le code du programme ; le core dump laisse une information en vue d'un diagnostic à l'attention du programmeur afin qu'il puisse trouver la trace de son erreur.