Kernel, shell, processus, fichiers, permissions, I/O, mémoire, IPC, signaux et /proc
Introduction
Linux est un système de type UNIX. Pour un développeur système, Linux est très intéressant parce qu’il expose beaucoup de mécanismes internes de façon directe : fichiers, processus, mémoire virtuelle, descripteurs de fichiers, signaux, pipes, sockets, pseudo-systèmes de fichiers, etc.
Contrairement à un environnement très encapsulé, Linux repose sur une philosophie assez simple :
- tout est vu comme une ressource manipulable ;
- beaucoup de ressources sont représentées par des fichiers ou des descripteurs ;
- les programmes communiquent avec le noyau via des appels système ;
- le shell permet d’orchestrer les programmes ;
- les processus sont isolés mais peuvent communiquer via des mécanismes prévus.
1. Le système d’exploitation et le noyau
Le terme système d’exploitation peut avoir deux sens.
- Au sens large : l’ensemble du système, avec le noyau, les outils, le shell, les bibliothèques, l’interface graphique, les utilitaires, etc.
- Au sens strict : le noyau, c’est-à-dire la partie centrale qui contrôle les ressources matérielles.
Le kernel est responsable de tâches fondamentales :
- gestion des processus ;
- ordonnancement CPU ;
- gestion mémoire ;
- gestion des fichiers ;
- gestion des périphériques ;
- réseau ;
- permissions et sécurité ;
- communication entre user mode et kernel mode.
Exemple :
Code: Select all
read(fd, buffer, size);
2. User mode et kernel mode
Linux sépare l’exécution en deux grands mondes.
User mode
Le user mode contient les programmes classiques :
- shell ;
- navigateur ;
- éditeur de texte ;
- serveur web ;
- programme C utilisateur ;
- outils système.
- à la mémoire du noyau ;
- au matériel ;
- aux instructions privilégiées du CPU ;
- à la mémoire d’un autre processus sans autorisation.
Le kernel mode est le mode privilégié. Le noyau peut accéder à l’ensemble de la machine.
Il peut :
- modifier les tables de pages ;
- planifier les processus ;
- communiquer avec les drivers ;
- gérer les interruptions ;
- accéder aux périphériques ;
- forcer l’arrêt d’un processus.
Schéma simplifié :
Code: Select all
Programme utilisateur
|
v
Bibliothèque C / wrapper
|
v
Appel système
|
v
Kernel Linux
|
v
Matériel / ressources système
3. Les appels système
Un appel système est une demande faite au noyau.
Exemples classiques :
Code: Select all
open()
read()
write()
close()
fork()
execve()
waitpid()
mmap()
pipe()
socket()
kill()
Exemple :
Code: Select all
#include <unistd.h>
int main()
{
write(1, "Bonjour\n", 8);
return 0;
}
- write() demande au noyau d’écrire des données ;
- 1 représente la sortie standard ;
- le texte est envoyé vers le terminal.
4. Le shell
Le shell est un interpréteur de commandes. Il lit les commandes entrées par l’utilisateur et lance les programmes correspondants.
Exemples de shells :
- sh ;
- bash ;
- zsh ;
- ksh ;
- fish.
Exemple :
Code: Select all
ls -la
Le shell gère aussi les redirections :
Code: Select all
ls > fichiers.txt
Il gère également les pipes :
Code: Select all
cat fichier.txt | grep Linux
- cat lit le fichier ;
- sa sortie est envoyée à grep ;
- grep filtre les lignes contenant "Linux".
5. Les utilisateurs et les groupes
Linux est un système multi-utilisateur. Chaque utilisateur possède un identifiant numérique appelé UID.
Exemple :
Code: Select all
id
Code: Select all
uid=1000(jean) gid=1000(jean) groups=1000(jean),27(sudo)
- uid est l’identifiant utilisateur ;
- gid est l’identifiant du groupe principal ;
- groups liste les groupes auxquels appartient l’utilisateur.
L’utilisateur spécial root possède l’UID 0.
Il a des privilèges très élevés sur le système.
Code: Select all
uid=0(root)
- modifier des fichiers système ;
- changer les permissions ;
- installer des services ;
- tuer des processus ;
- charger certains composants système ;
- administrer les utilisateurs.
6. La hiérarchie unique des fichiers
Linux utilise une seule arborescence de fichiers.
Contrairement à Windows, il n’y a pas de :
Code: Select all
C:\
D:\
E:\
Code: Select all
/
- /bin : commandes essentielles ;
- /sbin : commandes système ;
- /etc : fichiers de configuration ;
- /home : dossiers utilisateurs ;
- /root : dossier personnel de root ;
- /usr : programmes, bibliothèques, headers ;
- /var : fichiers variables, logs, caches ;
- /tmp : fichiers temporaires ;
- /dev : fichiers représentant les périphériques ;
- /proc : pseudo-système de fichiers exposant des infos kernel/processus ;
- /sys : informations sur les périphériques et le noyau.
Code: Select all
/home/jean/projets/test.c
7. Chemins absolus et chemins relatifs
Un chemin absolu commence depuis la racine.
Code: Select all
/home/jean/test.txt
Code: Select all
test.txt
./test.txt
../test.txt
- . représente le répertoire courant ;
- .. représente le répertoire parent.
Code: Select all
cd .
cd ..
pwd
8. Les types de fichiers
Sous Linux, le mot fichier ne désigne pas seulement un fichier texte ou binaire.
Il peut désigner plusieurs types d’objets :
- fichier régulier ;
- répertoire ;
- lien symbolique ;
- socket ;
- pipe ;
- périphérique caractère ;
- périphérique bloc.
Code: Select all
-rw-r--r-- 1 jean jean 1200 test.txt
drwxr-xr-x 2 jean jean 4096 projets
lrwxrwxrwx 1 jean jean 10 lien -> test.txt
- - : fichier régulier ;
- d : directory ;
- l : symbolic link ;
- c : character device ;
- b : block device ;
- p : pipe ;
- s : socket.
9. Les liens symboliques
Un lien symbolique est un fichier spécial qui pointe vers un autre chemin.
Création :
Code: Select all
ln -s /home/jean/test.txt lien.txt
Code: Select all
ls -l lien.txt
Code: Select all
lien.txt -> /home/jean/test.txt
Attention : si la cible est supprimée, le lien devient cassé.
10. Permissions Linux
Linux utilise un modèle de permissions simple mais très puissant.
Chaque fichier possède :
- un propriétaire ;
- un groupe ;
- des permissions pour le propriétaire ;
- des permissions pour le groupe ;
- des permissions pour les autres utilisateurs.
Code: Select all
-rwxr-xr--
Code: Select all
- rwx r-x r--
type user group others
- r : read, lecture ;
- w : write, écriture ;
- x : execute, exécution ou traversée pour un dossier.
Code: Select all
chmod +x programme
Pour retirer l’écriture aux autres :
Code: Select all
chmod o-w fichier.txt
Code: Select all
chmod 755 programme
Code: Select all
7 = rwx
5 = r-x
5 = r-x
- propriétaire : lecture, écriture, exécution ;
- groupe : lecture, exécution ;
- autres : lecture, exécution.
11. Le modèle I/O Linux
Une idée très importante sous UNIX/Linux est l’uniformité des entrées/sorties.
Les mêmes fonctions peuvent servir à lire ou écrire :
- des fichiers ;
- des pipes ;
- des sockets ;
- des terminaux ;
- certains périphériques.
Code: Select all
open()
read()
write()
close()
Code: Select all
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("test.txt", O_RDONLY);
char buffer[128];
ssize_t n = read(fd, buffer, sizeof(buffer));
close(fd);
return 0;
}
- open() ouvre le fichier ;
- read() lit les données ;
- close() ferme la ressource.
12. Les file descriptors
Un file descriptor est un entier qui représente une ressource ouverte dans un processus.
Exemple :
Code: Select all
int fd = open("test.txt", O_RDONLY);
Les trois premiers descripteurs sont standards :
- 0 : standard input, stdin ;
- 1 : standard output, stdout ;
- 2 : standard error, stderr.
Code: Select all
write(1, "Hello\n", 6);
write(2, "Erreur\n", 7);
Comparaison mentale :
Code: Select all
Linux file descriptor ~= HANDLE Windows
open() ~= CreateFile()
read() ~= ReadFile()
write() ~= WriteFile()
close() ~= CloseHandle()
13. Programmes et arguments de ligne de commande
Un programme C classique reçoit ses arguments avec :
Code: Select all
int main(int argc, char *argv[])
{
return 0;
}
argv est un tableau de chaînes.
Exemple d’exécution :
Code: Select all
./prog hello test
Code: Select all
argv[0] = "./prog"
argv[1] = "hello"
argv[2] = "test"
argc = 3
Code: Select all
#include <stdio.h>
int main(int argc, char *argv[])
{
for (int i = 0; i < argc; i++)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
Code: Select all
gcc main.c -o prog
Code: Select all
./prog linux kernel system
14. Les processus
Un processus est une instance d’un programme en cours d’exécution.
Un processus possède :
- un PID ;
- un espace mémoire virtuel ;
- des file descriptors ;
- un répertoire courant ;
- des variables d’environnement ;
- un utilisateur propriétaire ;
- un ou plusieurs threads ;
- un état d’exécution.
Code: Select all
ps aux
Code: Select all
echo $$
Code: Select all
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("PID = %d\n", getpid());
printf("PPID = %d\n", getppid());
return 0;
}
getppid() retourne le PID du parent.
15. Layout mémoire d’un processus
Un processus possède un espace d’adressage virtuel découpé en zones.
Schéma simplifié :
Code: Select all
+---------------------------+
| Stack |
+---------------------------+
| |
| Mémoire libre / mappings |
| |
+---------------------------+
| Heap |
+---------------------------+
| Data / BSS |
+---------------------------+
| Text |
+---------------------------+
- Text : code machine du programme ;
- Data : variables globales initialisées ;
- BSS : variables globales non initialisées ;
- Heap : mémoire dynamique, utilisée par malloc() ;
- Stack : appels de fonctions, variables locales, adresses de retour.
Code: Select all
#include <stdio.h>
#include <stdlib.h>
int global = 123;
int main()
{
int local = 456;
int *heap = malloc(sizeof(int));
printf("global = %p\n", (void*)&global);
printf("local = %p\n", (void*)&local);
printf("heap = %p\n", (void*)heap);
free(heap);
return 0;
}
16. Création de processus : fork()
Sous Linux, la création de processus repose historiquement sur fork().
fork() duplique le processus courant.
Après l’appel :
- le parent continue ;
- l’enfant continue ;
- les deux reprennent juste après le fork ;
- la valeur de retour permet de savoir dans quel processus on est.
Code: Select all
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid = fork();
if (pid == 0)
{
printf("Je suis l'enfant, PID = %d\n", getpid());
}
else
{
printf("Je suis le parent, PID enfant = %d\n", pid);
}
return 0;
}
- 0 dans le processus enfant ;
- > 0 dans le processus parent ;
- -1 en cas d’erreur.
17. Exécution d’un autre programme : execve()
fork() duplique le processus.
execve() remplace l’image mémoire du processus courant par un autre programme.
Modèle UNIX classique :
Code: Select all
fork()
|
+--> enfant
|
+--> execve()
Code: Select all
#include <unistd.h>
#include <stdio.h>
int main()
{
execlp("ls", "ls", "-la", NULL);
perror("execlp");
return 1;
}
18. Attendre un processus : waitpid()
Le parent peut attendre la fin d’un enfant avec waitpid().
Exemple :
Code: Select all
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t pid = fork();
if (pid == 0)
{
execlp("ls", "ls", "-la", NULL);
return 1;
}
else
{
int status;
waitpid(pid, &status, 0);
printf("L'enfant est terminé\n");
}
return 0;
}
19. Variables d’environnement
Chaque processus possède un environnement : un ensemble de chaînes clé=valeur.
Exemples :
Code: Select all
PATH=/usr/bin:/bin
HOME=/home/jean
SHELL=/bin/bash
USER=jean
Code: Select all
env
Code: Select all
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *home = getenv("HOME");
if (home != NULL)
printf("HOME = %s\n", home);
return 0;
}
20. Resource limits
Linux peut limiter les ressources d’un processus.
Exemples :
- taille maximale de fichier ;
- nombre maximal de fichiers ouverts ;
- taille de stack ;
- nombre de processus ;
- mémoire verrouillée ;
- temps CPU.
Code: Select all
ulimit -a
Code: Select all
getrlimit()
setrlimit()
Code: Select all
#include <stdio.h>
#include <sys/resource.h>
int main()
{
struct rlimit lim;
if (getrlimit(RLIMIT_NOFILE, &lim) == 0)
{
printf("Limite soft = %ld\n", (long)lim.rlim_cur);
printf("Limite hard = %ld\n", (long)lim.rlim_max);
}
return 0;
}
21. Memory mappings : mmap()
mmap() est une API très importante.
Elle permet de créer un mapping mémoire dans l’espace virtuel du processus.
Elle peut servir à :
- mapper un fichier en mémoire ;
- allouer de la mémoire anonyme ;
- créer de la mémoire partagée ;
- charger des bibliothèques ;
- gérer des zones mémoire avec permissions précises.
Code: Select all
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
Code: Select all
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
int main()
{
void *p = mmap(
NULL,
4096,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,
0
);
if (p == MAP_FAILED)
return 1;
strcpy((char*)p, "Hello mmap");
printf("%s\n", (char*)p);
munmap(p, 4096);
return 0;
}
Code: Select all
Linux mmap() ~= VirtualAlloc() + MapViewOfFile()
Windows sections ~= mappings Linux
22. Copy-On-Write
Après un fork(), Linux ne copie pas forcément immédiatement toute la mémoire du processus.
Il utilise souvent une stratégie appelée Copy-On-Write.
Principe :
- parent et enfant partagent temporairement les mêmes pages physiques ;
- les pages sont marquées en lecture seule ;
- si l’un des deux écrit dans une page, le noyau crée une copie privée ;
- cela évite de copier inutilement toute la mémoire.
Code: Select all
Parent
|
fork()
|
+--> Enfant
Au début :
Parent et enfant partagent les mêmes pages.
Si l'enfant écrit :
le noyau copie seulement la page modifiée.
23. Bibliothèques statiques et partagées
Linux utilise deux grands types de bibliothèques.
Bibliothèque statique
Extension courante :
Code: Select all
.a
Avantages :
- binaire plus autonome ;
- moins de dépendances externes.
- binaire plus gros ;
- mise à jour plus difficile ;
- duplication du code en mémoire.
Extension courante :
Code: Select all
.so
Exemple :
Code: Select all
libc.so
libpthread.so
libm.so
- moins de duplication ;
- mise à jour plus simple ;
- partage possible du code entre processus ;
- chargement dynamique.
Code: Select all
gcc main.c -o prog -lm
24. Communication inter-processus : IPC
Les processus sont isolés. Pour communiquer, ils doivent utiliser des mécanismes d’IPC.
Linux propose plusieurs mécanismes :
- pipes ;
- FIFO ;
- sockets UNIX ;
- sockets réseau ;
- shared memory ;
- message queues ;
- semaphores ;
- signals.
Un pipe permet de faire communiquer deux processus, souvent parent/enfant.
Code: Select all
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main()
{
int fd[2];
pipe(fd);
pid_t pid = fork();
if (pid == 0)
{
close(fd[1]);
char buffer[64];
read(fd[0], buffer, sizeof(buffer));
printf("Enfant a reçu : %s\n", buffer);
}
else
{
close(fd[0]);
char msg[] = "message depuis parent";
write(fd[1], msg, strlen(msg) + 1);
}
return 0;
}
- fd[0] sert à lire ;
- fd[1] sert à écrire.
25. Les signaux
Un signal est une interruption logicielle envoyée à un processus.
Exemples :
- SIGINT : Ctrl+C ;
- SIGTERM : demande propre de terminaison ;
- SIGKILL : terminaison forcée ;
- SIGSEGV : accès mémoire invalide ;
- SIGCHLD : un processus enfant s’est terminé ;
- SIGSTOP : suspension forcée ;
- SIGCONT : reprise.
Code: Select all
kill -TERM 1234
kill -9 1234
Code: Select all
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler(int sig)
{
printf("Signal reçu : %d\n", sig);
}
int main()
{
signal(SIGINT, handler);
while (1)
{
pause();
}
return 0;
}
26. Les threads
Un processus peut contenir plusieurs threads.
Les threads partagent :
- l’espace mémoire ;
- le heap ;
- les variables globales ;
- les file descriptors ;
- le code du programme.
- sa stack ;
- son contexte CPU ;
- ses registres ;
- son flot d’exécution.
Exemple :
Code: Select all
#include <pthread.h>
#include <stdio.h>
void* thread_func(void *arg)
{
printf("Thread lancé\n");
return NULL;
}
int main()
{
pthread_t t;
pthread_create(&t, NULL, thread_func, NULL);
pthread_join(t, NULL);
return 0;
}
Code: Select all
gcc main.c -o prog -pthread
Code: Select all
Linux pthread_create() ~= Windows CreateThread()
Linux pthread_join() ~= WaitForSingleObject()
Linux pthread_mutex_t ~= CRITICAL_SECTION / Mutex
27. Process groups et job control
Le shell gère les processus avec des notions propres à UNIX :
- session ;
- process group ;
- foreground process ;
- background process ;
- job control.
Code: Select all
./programme &
Code: Select all
jobs
Code: Select all
fg
Code: Select all
Ctrl+Z
Code: Select all
bg
28. Daemons
Un daemon est un processus de fond, souvent lancé au démarrage.
Equivalent conceptuel d’un service Windows.
Exemples :
- sshd : serveur SSH ;
- cron : tâches planifiées ;
- systemd : gestionnaire de services ;
- nginx : serveur web ;
- dbus-daemon : bus de communication.
- n’est pas attaché à un terminal utilisateur ;
- tourne en arrière-plan ;
- peut écrire dans des logs ;
- peut être contrôlé par systemd.
Code: Select all
systemctl status ssh
systemctl start ssh
systemctl stop ssh
29. Pseudo-terminaux
Un pseudo-terminal est une paire de périphériques virtuels qui imite un vrai terminal.
On retrouve ce concept dans :
- SSH ;
- terminal graphique ;
- tmux ;
- screen ;
- docker exec -it ;
- émulateurs de terminal.
- master : contrôlé par le programme hôte ;
- slave : vu par le programme lancé comme un terminal normal.
30. Date et temps
Linux utilise souvent l’epoch UNIX comme référence.
L’epoch UNIX correspond au :
Code: Select all
1 janvier 1970 00:00:00 UTC
Exemple :
Code: Select all
#include <stdio.h>
#include <time.h>
int main()
{
time_t now = time(NULL);
printf("time_t = %ld\n", (long)now);
printf("date = %s", ctime(&now));
return 0;
}
- temps réel ;
- temps CPU ;
- temps monotone ;
- temps utilisateur ;
- temps noyau.
31. Architecture client/serveur
Le modèle client/serveur est très utilisé sous Linux.
Un client demande un service.
Un serveur répond.
Exemples :
- navigateur web -> serveur HTTP ;
- client SSH -> sshd ;
- client SQL -> serveur de base de données ;
- application -> daemon local ;
- programme utilisateur -> service réseau.
- séparation des responsabilités ;
- centralisation d’un service ;
- partage de ressources ;
- communication réseau possible ;
- possibilité d’avoir plusieurs clients pour un serveur.
32. Realtime
Le temps réel ne signifie pas forcément “rapide”. Il signifie surtout que le système doit répondre dans un délai garanti ou borné.
Exemples :
- robotique ;
- audio faible latence ;
- industrie ;
- automobile ;
- systèmes embarqués ;
- contrôle matériel.
Exemples de mécanismes :
- scheduling temps réel ;
- priorités spécifiques ;
- verrouillage mémoire ;
- timers haute précision ;
- signaux temps réel ;
- PREEMPT_RT sur certains noyaux.
33. Le système de fichiers /proc
/proc est un pseudo-système de fichiers.
Il ne correspond pas à de vrais fichiers stockés sur disque. Il expose des informations du noyau et des processus.
Exemples :
Code: Select all
cat /proc/cpuinfo
cat /proc/meminfo
cat /proc/uptime
Code: Select all
/proc/PID/
Code: Select all
ls /proc/1234
- cmdline : ligne de commande ;
- environ : environnement ;
- exe : lien vers l’exécutable ;
- fd : descripteurs ouverts ;
- maps : mappings mémoire ;
- status : état du processus ;
- task : threads.
Code: Select all
cat /proc/self/maps
Exemple de lignes possibles :
Code: Select all
00400000-00452000 r-xp 00000000 08:01 12345 /bin/cat
00652000-00653000 r--p 00052000 08:01 12345 /bin/cat
7ffd12345000-7ffd12366000 rw-p 00000000 00:00 0 [stack]
- les plages d’adresses ;
- les permissions mémoire ;
- les fichiers mappés ;
- la stack ;
- le heap ;
- les bibliothèques.
34. Comparaison Linux / Windows
Pour quelqu’un venant de Win32/NT, certaines correspondances aident beaucoup.
Code: Select all
Linux Windows
-----------------------------------------------------
file descriptor HANDLE
open() CreateFile()
read() ReadFile()
write() WriteFile()
close() CloseHandle()
fork() + execve() CreateProcess()
waitpid() WaitForSingleObject()
pthread_create() CreateThread()
pthread_mutex_t CRITICAL_SECTION / Mutex
mmap() VirtualAlloc() / MapViewOfFile()
mprotect() VirtualProtect()
shared library .so DLL
daemon Windows Service
signal Console event / exception / APC-like concept
/proc/PID/maps VMMap / VAD-style view
pipe() Anonymous Pipe
FIFO Named Pipe
socket() Winsock socket
35. Mini-programme complet : fork + exec + wait
Ce programme crée un processus enfant, exécute ls, puis le parent attend sa fin.
Code: Select all
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t pid = fork();
if (pid == -1)
{
perror("fork");
return 1;
}
if (pid == 0)
{
execlp("ls", "ls", "-la", NULL);
perror("execlp");
return 1;
}
int status = 0;
if (waitpid(pid, &status, 0) == -1)
{
perror("waitpid");
return 1;
}
printf("Processus enfant terminé\n");
return 0;
}
Code: Select all
gcc main.c -o test
Code: Select all
./test
Code: Select all
parent
|
fork()
|
+-- child
|
+-- exec()
parent
|
waitpid()
36. Mini-programme complet : open/read/write
Ce programme ouvre un fichier, lit son contenu et l’écrit sur la sortie standard.
Code: Select all
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd = open("test.txt", O_RDONLY);
if (fd == -1)
{
perror("open");
return 1;
}
char buffer[256];
ssize_t n;
while ((n = read(fd, buffer, sizeof(buffer))) > 0)
{
write(1, buffer, n);
}
close(fd);
return 0;
}
- ouvrir une ressource ;
- obtenir un file descriptor ;
- lire avec read() ;
- écrire avec write() ;
- fermer avec close().
37. Mini-programme complet : lire /proc/self/maps
Ce programme lit les mappings mémoire du processus courant.
Code: Select all
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd = open("/proc/self/maps", O_RDONLY);
if (fd == -1)
{
perror("open");
return 1;
}
char buffer[512];
ssize_t n;
while ((n = read(fd, buffer, sizeof(buffer))) > 0)
{
write(1, buffer, n);
}
close(fd);
return 0;
}
Code: Select all
gcc maps.c -o maps
Code: Select all
./maps
38. Ce qu’il faut retenir
Les concepts fondamentaux du développement système Linux sont :
- kernel : cœur du système ;
- syscall : entrée contrôlée vers le noyau ;
- processus : programme en cours d’exécution ;
- thread : flot d’exécution dans un processus ;
- file descriptor : entier représentant une ressource ouverte ;
- shell : interpréteur et orchestrateur de commandes ;
- / : racine unique du système de fichiers ;
- /proc : pseudo-système de fichiers exposant des informations kernel ;
- fork() : création de processus ;
- execve() : remplacement de l’image mémoire ;
- waitpid() : attente d’un processus enfant ;
- mmap() : mapping mémoire ;
- signals : interruptions logicielles ;
- IPC : communication entre processus.
Code: Select all
open()
read()
write()
close()
Conclusion
Pour bien apprendre le développement système Linux, il faut penser autour de quelques piliers :
- le noyau contrôle les ressources ;
- les programmes passent par des appels système ;
- les ressources ouvertes sont représentées par des file descriptors ;
- les processus sont isolés ;
- les processus communiquent via IPC ;
- la mémoire virtuelle est manipulable avec mmap() ;
- le shell est un outil central ;
- /proc expose une partie de l’état interne du système.
- appels système en détail ;
- gestion des erreurs avec errno ;
- fichiers avancés ;
- répertoires ;
- processus zombies ;
- signaux avancés ;
- threads et synchronisation ;
- sockets ;
- epoll ;
- futex ;
- ptrace ;
- chargement ELF ;
- internals du kernel Linux.
