Programmation C Système & Réseau : Guide Complet

Telechargé par Edmond Gone
PROGRAMMATION C
Système & Réseau
────────────────────────────────────────
Guide complet du débutant au développeur système
Processus • Fichiers • Signaux • Mémoire • Sockets TCP/UDP
Pour débutants en C avec notions de programmation (Python, etc.)
Compilable sur Ubuntu / Debian (GCC, POSIX)
"C is quirky, flawed, and an enormous success." Dennis Ritchie
1. Introduction
1.1 Pourquoi apprendre C pour le système et le réseau ?
Imaginez votre ordinateur comme une grande ville. Python, JavaScript, Java sont des taxis avec GPS intégré
confortables, rapides à utiliser, mais vous ne contrôlez pas vraiment où vous allez. Le C, c'est apprendre
à conduire vous-même, à lire les panneaux, à choisir chaque route. Difficile au début, mais vous maîtrisez
vraiment la machine.
💡 C'est pour vous si... vous voulez comprendre comment fonctionnent les serveurs, les systèmes
d'exploitation, les protocoles réseau pas seulement les utiliser.
Voici pourquoi C est incontournable pour la programmation système et réseau :
Performance brute : C compile directement en code machine. Pas de machine virtuelle, pas
d'interpréteur. Le noyau Linux, Nginx, Redis, PostgreSQL tous écrits en C.
Proximité hardware : Vous manipulez directement la mémoire, les pointeurs, les descripteurs de
fichiers. C'est le langage le plus proche du matériel sans écrire de l'assembleur.
Standard POSIX : Toutes les API système Unix/Linux (processus, fichiers, sockets) sont définies en C.
Apprendre C c'est apprendre le système.
Portabilité : Du microcontrôleur embarqué au supercalculateur, C tourne partout.
Fondations : C++, Rust, Go, Python (l'interpréteur lui-même) héritent des concepts de C.
Critère
Python
C
Vitesse d'exécution
Lente (interprété)
Très rapide (compilé)
Gestion mémoire
Automatique (GC)
Manuelle (malloc/free)
Accès système
Via modules
Direct (POSIX)
Courbe d'apprentissage
Douce
Raide mais payante
Débogage
Facile
Complexe (mais GDB
aide)
1.2 Bref historique
1972 : Dennis Ritchie crée C chez Bell Labs pour réécrire Unix.
1978 : Kernighan & Ritchie publient "The C Programming Language" (K&R) la bible.
1989 : Standardisation ANSI C (C89/C90).
1999 : C99 tableaux de taille variable, commentaires //, stdint.h.
2011 : C11 threads natifs, _Generic. Nous utilisons C99/C11 dans ce guide.
1.3 Installation de l'environnement
TERMINAL
# Mise à jour des dépôts
sudo apt update
# Compilation : GCC + outils essentiels
sudo apt install gcc build-essential
# Débogage
sudo apt install gdb valgrind strace
# Vérification
gcc --version
# gcc (Ubuntu 13.x) 13.x.x
1.4 La commande de compilation
TERMINAL
# Compiler un programme C
gcc -Wall -Wextra -g -o mon_programme mon_programme.c
# Options :
# -Wall : Tous les warnings importants
# -Wextra : Warnings supplémentaires
# -g : Symboles de débogage (pour GDB)
# -o : Nom du fichier de sortie
# -std=c99 : Forcer le standard C99
1.5 Premier programme : Hello, Système !
CODE
#include <stdio.h> // printf
#include <unistd.h> // fork, getpid
#include <sys/wait.h> // wait
int main(void) {
pid_t pid = fork(); // Crée un processus enfant
if (pid < 0) {
perror("fork échoué");
return 1;
} else if (pid == 0) {
// Code exécuté par l'ENFANT
printf("Enfant : PID=%d, Parent PID=%d\n", getpid(), getppid());
} else {
// Code exécuté par le PARENT
printf("Parent : PID=%d, enfant créé PID=%d\n", getpid(), pid);
wait(NULL); // Attendre la fin de l'enfant
}
return 0;
}
TERMINAL
# Compilation et exécution
gcc -Wall -g -o hello_sys hello_sys.c
./hello_sys
# Parent : PID=1234, enfant créé PID=1235
# Enfant : PID=1235, Parent PID=1234
2. Bases Syntaxiques du C
2.1 Structure d'un programme C
CODE
#include <stdio.h> // Directive préprocesseur : inclut une bibliothèque
// Déclaration de fonction (prototype)
int addition(int a, int b);
// Point d'entrée du programme
int main(int argc, char *argv[]) {
int resultat = addition(3, 5);
printf("Résultat : %d\n", resultat);
return 0; // 0 = succès, autre = erreur
}
// Définition de la fonction
int addition(int a, int b) {
return a + b;
}
💡 Analogie #include c'est comme import en Python, mais le compilateur copie physiquement le
fichier. main() est le point d'entrée obligatoire de tout programme C.
2.2 Types primitifs et sizeof
CODE
#include <stdio.h>
#include <stdint.h> // Types à taille fixe (PRÉFÉREZ en système !)
int main(void) {
int entier = 42; // En général 4 octets
char lettre = 'A'; // 1 octet (-128 à 127)
double prec = 3.14159; // 8 octets double précision
// Types à taille garantie
int8_t i8 = -128; // Exactement 8 bits signé
uint8_t u8 = 255; // Exactement 8 bits non signé
int32_t i32 = 2000000; // Exactement 32 bits signé
uint64_t u64 = 18446744073709551615ULL;
printf("int = %zu octets\n", sizeof(int)); // 4
printf("char = %zu octet\n", sizeof(char)); // 1
printf("double = %zu octets\n", sizeof(double)); // 8
printf("void* = %zu octets\n", sizeof(void*)); // 8 (64 bits)
return 0;
}
Type
Taille
Plage
Format printf
char
1 octet
-128 à 127
%c / %d
unsigned char
1 octet
0 à 255
%u
int
4 octets
-2.1G à 2.1G
%d
unsigned int
4 octets
0 à 4.3G
%u
long
8 octets
±9.2 × 10^18
%ld
float
4 octets
~7 chiffres sig.
%f
double
8 octets
~15 chiffres
sig.
%lf
size_t
8 octets
0 à 18.4E
%zu
2.3 Opérateurs bitwise essentiels en système
Les opérateurs bitwise sont fondamentaux en programmation système. Les permissions Unix (rwxr-xr-x)
sont stockées sous forme de bits !
CODE
unsigned char flags = 0b00000000; // 8 bits à 0
unsigned char FLAG_READ = 0x01; // 0b00000001
unsigned char FLAG_WRITE = 0x02; // 0b00000010
unsigned char FLAG_EXEC = 0x04; // 0b00000100
flags |= FLAG_READ; // Activer READ → 0b00000001
flags |= FLAG_WRITE; // Activer WRITE → 0b00000011
flags &= ~FLAG_WRITE; // Désactiver WRITE → 0b00000001
int peut_lire = (flags & FLAG_READ) != 0; // Tester un bit
printf("Peut lire : %d\n", peut_lire); // 1
2.4 Contrôle de flux
CODE
// if / else if / else
int x = 42;
if (x < 0) printf("Négatif\n");
else if (x == 0) printf("Zéro\n");
else printf("Positif : %d\n", x);
// switch (utile pour les codes d'erreur / signaux)
int sig = 2; // SIGINT
switch (sig) {
case 2: printf("SIGINT (Ctrl+C)\n"); break;
case 9: printf("SIGKILL\n"); break;
default: printf("Signal %d\n", sig);
}
// Boucles
for (int i = 0; i < 5; i++) printf("%d ", i); // 0 1 2 3 4
int n = 10;
while (n > 0) { printf("%d ", n); n -= 3; } // 10 7 4 1
2.5 Passage de paramètres
CODE
// Passage par VALEUR : la fonction reçoit une COPIE
void doubler_valeur(int n) {
n = n * 2; // Ne modifie PAS l'original !
}
// Passage par POINTEUR : modifie la variable originale
void doubler_pointeur(int *n) {
*n = *n * 2; // Déréférencement → modifie l'original
}
int main(void) {
int x = 10;
doubler_valeur(x); // x vaut encore 10
doubler_pointeur(&x); // On passe l'ADRESSE → x = 20
1 / 25 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans l'interface ou les textes ? Ou savez-vous comment améliorer l'interface utilisateur de StudyLib ? N'hésitez pas à envoyer vos suggestions. C'est très important pour nous!