¶
Table des Matières - Maîtriser C sur Ubuntu : De la Syntaxe au Système
¶
Formation Complète pour Développeurs et DevOps (Édition 2025)
¶
README
¶
Module 1 : L’Écosystème C sous Linux
(Niveau Débutant)
¶
1.
Introduction et Histoire
1.1
Pourquoi le C en 2025 ?
1.2
La relation symbiotique entre C et UNIX/Linux
1.3
Normes du langage : ANSI C, C99, C11, C17, C23
1.3.1
Focus sur C23 : Nouveautés et état de l’adoption
1.3.2
Vérification du support compilateur
1.3.3
Pourquoi C11 reste la base recommandée en production
1.4
C vs C++ vs Rust : Quand choisir C ?
¶
2.
Configuration de l’environnement Ubuntu
2.1
Installation de la toolchain
2.2
Les versions de GCC et leur gestion
2.3
Choix de l’IDE/Éditeur
2.4
Configuration des extensions et outils de productivité
2.5
DevContainers : Environnement reproductible moderne
⭐
2.5.1
Qu’est-ce qu’un DevContainer ?
2.5.2
Structure du fichier .devcontainer.json
2.5.3
Configuration GCC/GDB/CMake/Valgrind
2.5.4
Intégration VS Code et onboarding
2.5.5
DevContainers comme source de vérité
¶
3.
La Chaîne de Compilation
3.1
Les 4 étapes détaillées
3.2
Visualisation du pipeline
3.3
Options de compilation GCC essentielles
3.4
Démystification du « Hello World »
3.5
Inspection des fichiers intermédiaires
3.6
Comprendre les symboles et la table des symboles
¶
Module 2 : Fondamentaux du Langage
(Niveau Débutant)
¶
4.
Types de données et Représentation mémoire
4.1
Types primitifs et leur taille
4.2
Signed vs Unsigned
4.3
Les constantes et les littéraux
4.4
Conversion de types
4.5
Endianness et portabilité
4.6
Nouveautés C23
¶
5.
Opérateurs et Structures de contrôle
5.1
Opérateurs arithmétiques
5.2
Opérateurs logiques
5.3
Opérateurs bit-à-bit
5.4
Conditions et optimisation
5.5
Boucles et contrôle de flux
5.6
Bonnes pratiques de formatage
5.7
Formatage automatique avec clang-format
⭐
5.7.1
Installation et configuration
5.7.2
Styles courants
5.7.3
Intégration IDE
5.7.4
Pre-commit hooks Git
5.7.5
Formatage dans le CI/CD
¶
6.
Les Fonctions
6.1
Déclaration, définition et prototypes
6.2
La Pile : Comprendre les Stack Frames
6.3
Passage par valeur
6.4
Valeurs de retour et codes d’erreur
6.5
La fonction main et ses paramètres
¶
Module 3 : La Gestion de la Mémoire
(Niveau Intermédiaire)
¶
7.
Les Pointeurs : Démystification
7.1
Concept d’adresse mémoire
7.2
Déclaration, déréférencement et adresse
7.3
L’arithmétique des pointeurs
7.4
Pointeurs void* et casting
7.5
Pointeurs NULL et dangling pointers
7.6
Pointeurs constants et const
7.7
Pointeurs restreints (restrict)
¶
8.
Tableaux et Chaînes de caractères
8.1
Relation tableaux et pointeurs
8.2
Tableaux multidimensionnels
8.3
Les chaînes en C
8.4
Manipulation de chaînes
8.5
Dangers des chaînes : Buffer Overflows
8.6
Fonctions sécurisées
8.7
Strings littérales et immutabilité
¶
9.
Allocation Dynamique
9.1
Stack vs Heap : Diagramme et différences
9.2
Durée de vie et performance
9.3
Les fonctions malloc, calloc, realloc et free
9.4
Gestion des erreurs d’allocation
9.5
Fuites mémoire : causes et prévention
9.6
Double free et corruption de tas
9.7
Stratégies d’allocation personnalisées
¶
Module 4 : Structures de Données et Modularité
(Niveau Intermédiaire)
¶
10.
Types définis par l’utilisateur
10.1
struct : Création d’objets complexes
10.2
Alignement mémoire et padding
10.3
Packed structures
10.4
union : Optimisation mémoire
10.5
enum : Code lisible et gestion d’états
10.6
typedef : Simplification de la syntaxe
10.7
Structures bit-fields
¶
11.
Structures de données dynamiques
11.1
Listes chaînées simples
11.2
Listes doublement chaînées
11.3
Piles et Files
11.4
Tables de hachage
11.5
Arbres binaires
11.6
Choix de la structure de données
11.7
Gestion mémoire des structures dynamiques
¶
12.
Organisation du code et Compilation modulaire
12.1
Fichiers d’en-tête et gardes d’inclusion
12.2
La portée des variables
12.3
Compilation séparée
12.4
Organisation d’un projet
12.5
Conventions de nommage et standards
12.6
Forward declarations et dépendances circulaires
¶
Module 5 : Outillage DevOps et Automatisation
(Niveau Avancé)
¶
13.
Build Systems : De Make à CMake
⭐
13.1
CMake : Le standard moderne
🔥
13.1.1
Pourquoi CMake ?
13.1.2
Installation et premiers pas
13.1.3
Structure d’un CMakeLists.txt
13.1.4
Targets, properties et generators
13.1.5
Gestion des dépendances
13.1.6
Build types
13.1.7
Out-of-source builds
13.1.8
Intégration VS Code et CLion
13.2
GNU Make : Fondamentaux
13.2.1
Syntaxe des Makefile
13.2.2
Règles, cibles et dépendances
13.2.3
Variables et macros
13.2.4
Pattern rules et automatic variables
13.3
Comparaison Make vs CMake
13.4
Autres build systems
¶
14.
Les Bibliothèques
14.1
Bibliothèques statiques (.a)
14.1.1
Compilation avec ar et ranlib
14.1.2
Linking statique
14.2
Bibliothèques dynamiques (.so)
14.2.1
Compilation avec -fPIC
14.2.2
Versioning et SONAME
14.2.3
Résolution de symboles au runtime
14.3
Différences statiques vs dynamiques
14.4
Gestion du LD_LIBRARY_PATH
14.5
ldd et ldconfig
14.6
Création d’une API propre
14.7
Symbol visibility
¶
15.
Débogage et Analyse de Qualité
⭐
15.1
Sanitizers : Première ligne de défense
🔥
15.1.1
AddressSanitizer (ASan)
15.1.2
UndefinedBehaviorSanitizer (UBSan)
15.1.3
ThreadSanitizer (TSan)
15.1.4
LeakSanitizer (LSan)
15.1.5
Compilation avec sanitizers
15.1.6
Performance et overhead
15.1.7
Intégration dans le workflow
15.2
Utilisation de GDB
15.2.1
Breakpoints, watchpoints, catchpoints
15.2.2
Stepping
15.2.3
Backtrace et analyse de la pile
15.2.4
Inspection des variables
15.2.5
GDB TUI mode
15.3
GDB avancé
15.3.1
Core dumps
15.3.2
Debugging distant
15.3.3
Scripts GDB
15.3.4
rr (Time Travel Debugging)
15.4
Détection de fuites avec Valgrind
15.4.1
Memcheck
15.4.2
Interprétation des rapports
15.4.3
Suppression files
15.5
Valgrind avancé
15.5.1
Helgrind
15.5.2
Cachegrind
15.5.3
Callgrind
15.5.4
Massif
15.6
Analyse statique de code
15.6.1
cppcheck
15.6.2
clang-tidy
15.6.3
Configuration et intégration continue
15.7
Code coverage
15.7.1
gcov
15.7.2
lcov
15.7.3
Intégration dans le CI
¶
Module 6 : Programmation Système Linux
(Niveau Expert)
¶
16.
Gestion des Fichiers et Entrées/Sorties
16.1
Descripteurs de fichiers
16.2
Appels système
16.3
Différence appels système vs bibliothèque
16.4
Permissions et modes
16.5
I/O bufferisé vs non bufferisé
16.6
dup, dup2 et redirection
16.7
I/O multiplexing
16.8
I/O asynchrone (AIO)
¶
17.
Processus et Signaux
17.1
Création de processus
17.2
Les PIDs et hiérarchie
17.3
Processus orphelins et zombies
17.4
Variables d’environnement
17.5
Gestion des signaux
17.6
Signaux courants
17.7
Masquage de signaux
17.8
Pipes anonymes
17.9
Named pipes (FIFO)
¶
18.
Threads et Concurrence (POSIX)
⭐
18.1
Introduction à pthread
18.2
Création et terminaison de threads
18.3
Passage de paramètres
18.4
Threads détachés vs joinable
18.5
Problèmes de concurrence : Race conditions
18.6
Mutex et sections critiques
18.7
Deadlocks
18.8
Variables de condition
18.9
Sémaphores POSIX
18.10
Concurrence lock-free avec les Atomics (C11)
🔥
18.10.1
Introduction à stdatomic.h
18.10.2
Types atomiques
18.10.3
Memory ordering
18.10.4
Compare-and-swap (CAS)
18.10.5
Atomics vs mutex
18.10.6
Performance et cas d’usage
18.11
Read-write locks
18.12
Thread-local storage
18.13
Barrières de threads
¶
19.
Mémoire partagée et IPC avancé
19.1
Shared memory
19.2
Sémaphores System V
19.3
Message queues System V
19.4
POSIX IPC vs System V IPC
19.5
Memory-mapped files (mmap)
¶
20.
Réseau (Sockets)
20.1
Modèle Client/Serveur
20.2
Architecture TCP/IP
20.3
Sockets TCP
20.4
Sockets UDP
20.5
Gestion des erreurs réseau
20.6
Options de sockets
20.7
Résolution de noms
20.8
Serveur concurrent
20.9
Non-blocking I/O et epoll
20.10
Création d’un mini-serveur HTTP
¶
21.
Introduction à eBPF
⭐🔥
21.1
Qu’est-ce qu’eBPF ?
21.1.1
Histoire : de BPF classique à eBPF
21.1.2
Pourquoi eBPF révolutionne Linux
21.2
Architecture eBPF
21.2.1
BPF programs
21.2.2
BPF maps
21.2.3
Le verifier
21.2.4
JIT compilation
21.3
Use cases DevOps et observabilité
21.3.1
Tracing et monitoring
21.3.2
Networking
21.3.3
Sécurité
21.3.4
Performance analysis
21.4
Toolchain eBPF
21.4.1
libbpf
21.4.2
bpftool
21.4.3
Compilation et chargement
21.5
Premier programme eBPF
21.5.1
Hello World : tracer les appels système
21.5.2
Utilisation de maps
21.5.3
Attacher à des hooks kernel
21.6
eBPF dans l’écosystème moderne
21.6.1
Cilium
21.6.2
Pixie
21.6.3
Ressources pour aller plus loin
¶
Module 7 : Techniques Avancées et Optimisation
(Niveau Expert)
¶
22.
Pointeurs avancés
22.1
Pointeurs de fonctions (Callbacks)
22.2
Tableaux de pointeurs de fonctions
22.3
Pointeurs multi-niveaux
22.4
Pointeurs opaques
22.5
Fonctions variadiques
22.6
va_list et macros variadiques
¶
23.
Macros et Préprocesseur avancé
23.1
Macros paramétrées
23.2
Stringification et concaténation
23.3
Compilation conditionnelle
23.4
Macros cross-platform
23.5
Dangers et pièges des macros
23.6
Macros prédéfinies utiles
23.7
X-Macros
¶
24.
Gestion avancée de la mémoire
24.1
RAII-like en C :
attribute
((cleanup))
24.1.1
Extension GNU
24.1.2
Utilisation dans systemd et GLib
24.1.3
Patterns pour fichiers, mémoire, locks
24.1.4
Limitations et portabilité
24.2
Custom allocators
24.3
Garbage collection en C
¶
25.
Gestion des erreurs robuste
25.1
Codes de retour vs exceptions simulées
25.2
La variable errno
25.3
Patterns de gestion d’erreurs
25.4
Assertions
25.5
Design by contract
25.6
Logging
¶
26.
Sécurité et Code défensif
26.1
Secure C Coding Standards (CERT C)
26.2
Validation des entrées
26.3
Prévention des buffer overflows
26.4
Format string vulnerabilities
26.5
Integer overflow
26.6
Principe du moindre privilège
26.7
Static analysis et fuzzing
26.8
Compilation avec hardening flags
¶
27.
Optimisation et Performance
27.1
Flags d’optimisation GCC
27.2
Comprendre l’optimiseur
27.3
Profiling
27.4
Cache awareness
27.5
Branch prediction
27.6
Optimisations algorithmiques
27.7
Vectorisation et SIMD
27.8
Link-Time Optimization (LTO)
27.9
Profile-Guided Optimization (PGO)
27.10
Benchmarking rigoureux
¶
28.
Interopérabilité
28.1
Appeler du C depuis Python
28.2
Appeler du C depuis Go
28.3
Interfaçage avec Rust (FFI)
28.4
ABI et compatibilité
28.5
extern « C » pour C++
28.6
Name mangling
¶
Module 8 : C dans un Pipeline CI/CD
(Bonus DevOps)
⭐
¶
29.
Tests et Qualité
29.1
Philosophie du testing en C
29.2
Tests unitaires : frameworks
29.3
Écriture de tests et assertions
29.4
Mocking et stubbing
29.5
Tests d’intégration
29.6
Mesure de couverture
29.7
Test-Driven Development (TDD)
¶
30.
Intégration Continue moderne
🔥
30.1
GitHub Actions pour projets C
30.1.1
Structure du workflow
30.1.2
Matrix build
30.1.3
Build avec CMake en CI
30.1.4
Exécution des tests unitaires
30.1.5
Vérification avec sanitizers
30.1.6
Analyse Valgrind automatisée
30.1.7
Code coverage et Codecov
30.1.8
Static analysis
30.1.9
Publication d’artifacts
30.2
GitLab CI pour projets C
30.3
Jenkins : pipelines déclaratifs
30.4
Gestion des caches
30.5
Notifications et reporting
¶
31.
Cross-compilation et Déploiement
31.1
Cross-compilation : principes
31.2
Compiler pour ARM depuis x86
31.3
CMake et cross-compilation
31.4
QEMU pour tester les binaires
31.5
Packaging Linux : .deb
31.6
Packaging Linux : .rpm
31.7
AppImage
31.8
Conteneurisation : Docker multi-stage
31.9
Distribution de bibliothèques partagées
¶
32.
Documentation et Maintenance
32.1
Documentation du code : Doxygen
32.1.1
Syntaxe des commentaires
32.1.2
Génération HTML/PDF
32.1.3
Intégration dans le CI
32.2
README et documentation utilisateur
32.3
Gestion de versions avec Git
32.3.1
Commits atomiques
32.3.2
Branches et workflow
32.3.3
Gestion des binaires
32.4
Changelog et versioning sémantique
32.5
Maintenance du code legacy
32.5.1
Refactoring progressif
32.5.2
Ajout de tests
32.5.3
Modernisation
¶
Module 9 : Projets de Synthèse et Études de Cas
(Optionnel)
¶
33.
Analyse de code open-source
33.1
Méthodologie de lecture de code
33.2
Étude de cas : Git
33.3
Étude de cas : Redis
33.4
Étude de cas : Nginx
33.5
Contribution à des projets C open-source
33.5.1
Trouver un bon premier issue
33.5.2
Comprendre le coding style
33.5.3
Soumettre une Pull Request
¶
34.
Études de cas DevOps
34.1
Création d’un outil CLI système
34.1.1
Parsing d’arguments
34.1.2
Interaction avec le système
34.1.3
Output formaté
34.2
Parser de logs haute performance
34.2.1
Lecture efficace de gros fichiers
34.2.2
Expressions régulières
34.2.3
Agrégation et statistiques
34.3
Agent de monitoring système
34.3.1
Collecte de métriques
34.3.2
Export Prometheus
34.3.3
Daemonisation
34.4
Serveur web minimaliste
34.4.1
Architecture event-driven
34.4.2
HTTP parsing
34.4.3
Static file serving
¶
35.
Debugging de code complexe
35.1
Analyse de core dumps en production
35.2
Résolution de memory leaks
35.3
Investigation de race conditions
35.4
Debugging de deadlocks
35.5
Performance debugging
¶
Annexes et Ressources
¶
A.
Références essentielles
A.1
Standards C officiels
A.2
Man pages Linux essentielles
A.3
Livres de référence recommandés
A.4
Ressources en ligne et communautés
¶
B.
Antisèches (Cheat sheets)
B.1
Options GCC
B.2
Commandes GDB
B.3
Appels système Linux
B.4
POSIX threads API
B.5
CMake commandes principales
B.6
Flags de sanitizers et Valgrind
¶
C.
Configuration de l’environnement
C.1
.vimrc optimisé pour C
C.2
VS Code settings.json et extensions
C.3
.clang-format exemple
C.4
.devcontainer.json complet
C.5
GitHub Actions workflow template
¶
D.
Glossaire
D.1
Terminologie C
D.2
Terminologie système Linux
D.3
Acronymes DevOps
D.4
Termes eBPF
¶
🎯
Parcours recommandés selon le profil
Développeur Backend → DevOps
SysAdmin → Ingénieur Système
Embedded → Linux Embarqué
Débutant Complet → Ingénieur C Full-Stack
Formation Complète (intensive)
¶
📊
Ressources complémentaires
Matrice de Compétences par Parcours
Critères d’évaluation et certification
Conseils pour réussir
Projets pratiques recommandés