C fork

De The Linux Craftsman
Aller à la navigation Aller à la recherche

Introduction

Un fork est un processus lourd, comprenez par là que l'intégralité du contexte d'exécution du processus père est recopié dans le nouveau processus fils. Ne cherchez pas, comme avec les threads, a échanger des variables entre les processus car cela ne marchera pas. Il faut utiliser des techniques de communication inter-processus comme les tubes, socket ou encore sémaphores...

Fonctionnement

Pour créer un fork, il suffit d'appeler la fonction du même nom. Cette fonction aura différentes valeurs de retour en fonction du processus dans lequel on se trouve:

  • -1 → il y a une erreur ;
  • 0 → on est dans le processus fils ;
  • Le PID du fils → on est dans le processus père.

La valeur retournée par la fonction fork est de type pid_t, c'est pourquoi il faut obligatoirement inclure le fichier <sys/types.h>.

Dans le cas d'une erreur, celle-ci sera accessible grâce à la variable globale errno, il faudra donc inclure le fichier entête <errno.h>.

Fonctions annexes

Voici quelques fonctions annexes bien pratiques:

  • getpid → retourne le PID du processus appelant, de type pid_t :
printf("Mon PID est %i\n", getpid()); // affichera par exemple "Mon PID est 14804"
  • getppid → retourne le PPID du processus appelant, de type pid_t :
printf("Mon PPID est %i\n", getppid()); // affichera par exemple "Mon PPID est 14403"
  • getuid → retourne l'UID du processus appelant, de type uid_t :
printf("Mon UID est %i\n", getuid()); // affichera par exemple "Mon UID est 0"
  • getgid → retourne le GID du processus appelant, de type gid_t :
printf("Mon GID est %i\n", getgid()); // affichera par exemple "Mon GID est 0"

Création

Ci-dessous un exemple de création d'un processus lourd :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
	pid_t pid = fork();
	if (pid == -1) {
		// Il y a une erreur
		perror("fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		// On est dans le fils
		printf("Mon PID est %i et celui de mon père est %i\n", getpid(),	getppid());
	} else {
		// On est dans le père
		printf("Mon PID est %i et celui de mon fils est %i\n", getpid(), pid);
	}
	return EXIT_SUCCESS;
}

Cette exemple peut retourner la sortie suivante :

Mon PID est 15150 et celui de mon fils est 15151
Mon PID est 15151 et celui de mon père est 15150

Cependant, on peut très bien avoir cela:

Mon PID est 15197 et celui de mon fils est 15198
Mon PID est 15198 et celui de mon père est 1

On voit que le numéro de processus du père est devenu 1. Cela vient du faite que, lorsque le père se termine, le fils est automatiquement rattaché au processus de PID 1 pour ne pas devenir un processus orphelin.