
Les secrets du dessous de l'ordinateur
Description
Introduction au livre
Que se passe-t-il à l'intérieur de votre ordinateur lorsque vous exécutez le code ?
Du système d'exploitation au processeur, en passant par la synchronisation et les principes de mise en œuvre des entrées/sorties,
Découvrons ensemble les secrets qui se cachent sous le capot de votre ordinateur et qui vont modifier votre code !
Nous avons tous probablement déjà fait l'expérience de nous demander : « Hein ? Pourquoi ce code ne fonctionne-t-il pas ? »
Même si votre code s'exécute correctement, vous ne savez souvent pas comment il fonctionne, ce qui se passe en interne lorsque votre ordinateur l'exécute, pourquoi divers problèmes surviennent et comment les optimiser.
Ce livre s'adresse aux développeurs qui ne se contentent pas de quelques lignes de code s'exécutant sans erreur, mais qui réfléchissent plutôt à ce qui se passe à l'intérieur et à son impact sur le code.
Ce livre examine la structure d'un système informatique, qui est abstraite couche par couche, une à une.
En commençant par les langages de programmation et les compilateurs, nous examinerons les systèmes d'exploitation et les processus, les threads et les coroutines, la synchronisation, la mémoire et les principes de mise en œuvre des processeurs, des caches et des entrées/sorties.
Le fonctionnement interne d'un système informatique, qui peut sembler difficile à comprendre, est expliqué à l'aide de diverses métaphores du quotidien et de plus de 300 illustrations, ce qui le rend relativement accessible.
Les développeurs débutants peuvent apprendre les bases de l'informatique de manière systématique et facile, et les développeurs expérimentés peuvent trouver de nouvelles idées tout en organisant leurs connaissances existantes.
Du système d'exploitation au processeur, en passant par la synchronisation et les principes de mise en œuvre des entrées/sorties,
Découvrons ensemble les secrets qui se cachent sous le capot de votre ordinateur et qui vont modifier votre code !
Nous avons tous probablement déjà fait l'expérience de nous demander : « Hein ? Pourquoi ce code ne fonctionne-t-il pas ? »
Même si votre code s'exécute correctement, vous ne savez souvent pas comment il fonctionne, ce qui se passe en interne lorsque votre ordinateur l'exécute, pourquoi divers problèmes surviennent et comment les optimiser.
Ce livre s'adresse aux développeurs qui ne se contentent pas de quelques lignes de code s'exécutant sans erreur, mais qui réfléchissent plutôt à ce qui se passe à l'intérieur et à son impact sur le code.
Ce livre examine la structure d'un système informatique, qui est abstraite couche par couche, une à une.
En commençant par les langages de programmation et les compilateurs, nous examinerons les systèmes d'exploitation et les processus, les threads et les coroutines, la synchronisation, la mémoire et les principes de mise en œuvre des processeurs, des caches et des entrées/sorties.
Le fonctionnement interne d'un système informatique, qui peut sembler difficile à comprendre, est expliqué à l'aide de diverses métaphores du quotidien et de plus de 300 illustrations, ce qui le rend relativement accessible.
Les développeurs débutants peuvent apprendre les bases de l'informatique de manière systématique et facile, et les développeurs expérimentés peuvent trouver de nouvelles idées tout en organisant leurs connaissances existantes.
- Vous pouvez consulter un aperçu du contenu du livre.
Aperçu
indice
Chapitre 1 : Du langage de programmation à l'exécution du programme : voici comment cela se passe.
1.1 Et si vous inventiez un langage de programmation ?
__1.1.1 Genèse : Le processeur est un idiot intelligent
__1.1.2 Le langage assembleur apparaît
1.1.3 Détails des couches de bas niveau vs abstractions des couches de haut niveau
__1.1.4 Règles complètes : Le début d’un langage de programmation de haut niveau
__1.1.5 Inception et récursivité : l’essence du code
__1.1.6 Faire comprendre la récursivité aux ordinateurs
__1.1.7 Excellent traducteur : Compilateur
__1.1.8 La naissance des langues interprétées
1.2 Comment fonctionne un compilateur ?
__1.2.1 Le compilateur est un programme normal, rien de spécial.
__1.2.2 Extraction de chaque jeton
1.2.3 Ce que le jeton tente d'exprimer
__1.2.4 Existe-t-il des anomalies dans l'arbre syntaxique généré ?
1.2.5 Génération de code intermédiaire à partir d'arbres syntaxiques
__1.2.6 Génération de code
1.3 Le secret inavouable du Linker
__1.3.1 Voici comment fonctionne l'éditeur de liens
1.3.2 Interprétation des symboles : Offre et demande
__1.3.3 Bibliothèques statiques, bibliothèques dynamiques et exécutables
1.3.4 Avantages et inconvénients des bibliothèques dynamiques
1.3.5 Relocalisation : Détermination de l'adresse d'un symbole au moment de l'exécution
1.3.6 Structure de la mémoire virtuelle et de la mémoire programme
1.4 Pourquoi l'abstraction est importante en informatique
__1.4.1 Programmation et abstraction
__1.4.2 Conception et abstraction du système
1.5 Résumé
Chapitre 2 Le programme s'est exécuté, mais je ne sais pas ce qui se passe.
2.1 Comprendre les principes fondamentaux des systèmes d'exploitation, des processus et des threads
2.1.1 Tout commence avec le processeur
2.1.2 Du processeur au système d'exploitation
__2.1.3 Le processus est très bon, mais reste néanmoins peu pratique.
__2.1.4 Évolution des processus vers les threads
__2.1.5 Multithreading et structure de la mémoire
__2.1.6 Exemple d'utilisation des threads
__2.1.7 Fonctionnement du pool de threads
__2.1.8 Nombre de threads dans le pool de threads
2.2 Ressources de processus partagées entre les threads
__2.2.1 Ressources réservées aux threads
__2.2.2 Zone de code : Toutes les fonctions peuvent être placées dans des threads et exécutées.
__2.2.3 Zone de données : Tous les threads peuvent accéder aux variables de la zone de données.
__2.2.4 Zone du tas : les pointeurs sont essentiels
__2.2.5 Zone de pile : Données privées au sein d’un espace partagé
__2.2.6 Bibliothèques de liens dynamiques et fichiers
__2.2.7 Stockage réservé aux threads
2.3 Comment dois-je écrire exactement du code thread-safe ?
__2.3.1 Liberté et contraintes
__2.3.2 Qu'est-ce que la sécurité des fils ?
__2.3.3 Ressources spécifiques au thread et partagées
__2.3.4 Utiliser uniquement les ressources spécifiques au thread
__2.3.5 Ressources spécifiques au thread et paramètres de fonction
__2.3.6 Utilisation des variables globales
__2.3.7 Stockage réservé aux threads
__2.3.8 Valeurs de retour de la fonction
__2.3.9 Appel de code non thread-safe
__2.3.10 Comment implémenter du code thread-safe ?
2.4 Comment les programmeurs doivent-ils comprendre les coroutines ?
__2.4.1 Fonctions générales
__2.4.2 Des fonctions régulières aux coroutines
__2.4.3 Explication intuitive des coroutines
__2.4.4 Les fonctions ne sont qu'un cas particulier de coroutines
__2.4.5 Historique des coroutines
__2.4.6 Comment les coroutines sont-elles implémentées ?
2.5 Comprendre parfaitement les fonctions de rappel
__2.5.1 Tout commence par l'exigence suivante :
2.5.2 Pourquoi les rappels sont nécessaires
__2.5.3 Rappels asynchrones
__2.5.4 Les rappels asynchrones ouvrent la voie à une nouvelle approche de la programmation
__2.5.5 Définition de la fonction de rappel
__2.5.6 Deux types de rappel
__2.5.7 Le problème des rappels asynchrones : l’enfer des rappels
2.6 Comprendre parfaitement les concepts synchrones et asynchrones
__2.6.1 Programmeur travailleur
__2.6.2 Passer des appels téléphoniques et envoyer des courriels
__2.6.3 Appel synchrone
__2.6.4 Appels asynchrones
__2.6.5 Opérations synchrones et asynchrones sur les serveurs Web
2.7 Ah oui ! Il existe des modes bloquants et non bloquants.
__2.7.1 Blocage et non-blocage
2.7.2 Le problème fondamental du blocage : E/S
2.7.3 E/S non bloquantes et asynchrones
2.7.4 Analogie avec la commande d'une pizza
__2.7.5 Motivation et blocage
__2.7.6 Asynchrone et non bloquant
2.8 Mise en œuvre d'un serveur à haute concurrence et hautes performances
__2.8.1 Multitraitement
__2.8.2 Multithreading
__2.8.3 Bouclage d'événements et pilotage par événements
__2.8.4 Premier problème : Sources d’événements et multiplexage des E/S
__2.8.5 Deuxième problème : Boucles d’événements et multithreading
__2.8.6 Fonctionnement d'un café : le modèle du répondant
__2.8.7 Cycle d'événements et entrées/sorties
__2.8.8 Fonctions asynchrones et de rappel
__2.8.9 Coroutines : Programmation asynchrone avec des méthodes synchrones
__2.8.10 Processeur, Threads, Coroutines
2.9 Parcours d'un système informatique : des données, du code, des rappels et des fermetures aux conteneurs et aux machines virtuelles
__2.9.1 Code, données, variables, pointeurs
__2.9.2 Fonctions de rappel et fermetures
__2.9.3 Technologie des conteneurs et des machines virtuelles
2.10 Résumé
Chapitre 3 : Hiérarchies de bas niveau ? Commençons par le casier appelé mémoire.
3.1 La nature de la mémoire, des pointeurs et des références
__3.1.1 Quelle est la nature de la mémoire ? Casiers, bits, octets et objets.
3.1.2 De la mémoire aux variables : que signifient les variables ?
3.1.3 Des variables aux pointeurs : Comprendre les pointeurs
__3.1.4 Le pouvoir et la destruction des pointeurs : capacités et responsabilités
3.1.5 Du pointeur à la référence : masquage des adresses mémoire
3.2 À quoi ressemble un processus en mémoire ?
3.2.1 Mémoire virtuelle : ce que vous voyez n’est pas toujours ce que vous obtenez
3.2.2 Pages et tables de pages : du virtuel au réel
3.3 Zone de pile : Comment les appels de fonction sont-ils implémentés ?
__3.3.1 Outils pour programmeurs : Fonctions
3.3.2 Suivi de l'activité d'appel de fonction : Pile
3.3.3 Cadres et zones de pile : une perspective macro
__3.3.4 Comment les sauts et les retours de fonction sont-ils implémentés ?
__3.3.5 Comment le passage des paramètres et les valeurs de retour sont-ils implémentés ?
__3.3.6 Où sont les variables locales ?
__3.3.7 Sauvegarde et restauration des registres
__3.3.8 Dressons un tableau d'ensemble, où en sommes-nous maintenant ?
3.4 Zone de tas : Comment l'allocation dynamique de mémoire est-elle implémentée ?
3.4.1 Pourquoi avons-nous besoin d'espace mémoire ?
3.4.2 Implémentation directe de l'allocateur de mémoire malloc
3.4.3 Du parking à la gestion de la mémoire
3.4.4 Gestion des fragments de mémoire libre
3.4.5 Suivi de l'état d'allocation de mémoire
3.4.6 Comment choisir une zone de mémoire libre : stratégie d’allocation
3.4.7 Allocation de mémoire
3.4.8 Libération de la mémoire
3.4.9 Fusion efficace des fragments de mémoire libre
3.5 Que se passe-t-il au niveau le plus bas lors de l'allocation de mémoire ?
__3.5.1 État d'exécution du processeur Ciel, Terre et Humain
3.5.2 État du noyau et état de l'utilisateur
__3.5.3 Portail : Appels système
__3.5.4 Bibliothèque standard : Masquer les différences entre les systèmes
3.5.5 Lorsque la zone de tas est saturée en mémoire
__3.5.6 Demande de mémoire au système d'exploitation : brk
__3.5.7 Sous l'iceberg : la mémoire virtuelle est le boss final
3.5.8 L'histoire complète de l'allocation de mémoire
3.6 Comment le pool de mémoire est-il implémenté pour les serveurs hautes performances ?
3.6.1 Pools de mémoire vs. allocateurs de mémoire à usage général
3.6.2 Principes de la technologie de pool de mémoire
3.6.3 Implémentation d'un pool de mémoire très simple
3.6.4 Implémentation d'un pool de mémoire légèrement plus complexe
__3.6.5 Problèmes de sécurité des threads avec les pools de mémoire
3.7 Bogues courants liés à la mémoire
3.7.1 Retourner un pointeur vers une variable locale
3.7.2 Mauvaise compréhension de l'arithmétique des pointeurs
__3.7.3 Déréférencement d'un pointeur problématique
3.7.4 Lecture de la mémoire non initialisée
3.7.5 Référencement d'une mémoire déjà libérée
__3.7.6 Les indices des tableaux commencent à 0
__3.7.7 Stack Overflow
__3.7.8 Fuite de mémoire
3.8 Pourquoi les SSD ne peuvent-ils pas être utilisés comme mémoire ?
3.8.1 Différence entre la lecture/écriture en mémoire et la lecture/écriture sur disque
__3.8.2 Limites de mémoire virtuelle
__3.8.3 Problèmes liés à la durée de vie des SSD
3.9 Résumé
Chapitre 4 : Des transistors aux processeurs : Rien n'est plus important que cela.
4.1 Ce petit jouet s'appelle un CPU.
4.1.1 Grande invention
4.1.2 Conjonction logique, conjonction logique et négation logique
__4.1.3 Le Tao donne naissance à un, un donne naissance à deux, deux donne naissance à trois, et trois donne naissance à toutes choses.
__4.1.4 D’où provient la puissance de calcul ?
4.1.5 Capacité de mémorisation exceptionnelle
4.1.6 La naissance des registres et de la mémoire
4.1.7 Matériel ou logiciel ? Appareils à usage général
4.1.8 Technologie matérielle de base : Instructions machine
4.1.9 Interface logiciel-matériel : Jeu de commandes
4.1.10 Les circuits nécessitent des conducteurs
__4.1.11 Une grande réussite, le processeur est né !
4.2 Que fait le processeur lorsqu'il est inactif ?
__4.2.1 Quel est le taux d'utilisation du processeur de votre ordinateur ?
4.2.2 Gestion et planification des processus
4.2.3 Vérification de l'état de la file d'attente : une meilleure conception
4.2.4 Tout retourne au processeur
4.2.5 Processus inactifs et états de faible consommation du processeur
__4.2.6 Rompre la boucle infinie : les interruptions
4.3 Comment le processeur reconnaît-il les nombres ?
__4.3.1 Le nombre 0 et les entiers positifs
__4.3.2 Entiers signés
4.3.3 Ajouter un signe moins à un nombre positif donne immédiatement le nombre négatif correspondant : représentation signe-magnitude
4.3.4 Inversion de la représentation signe-magnitude : complément à 1
4.3.5 Addition de deux nombres qui ne sont pas simples
4.3.6 Représentation conviviale pour ordinateur : le complément à deux
__4.3.7 Le processeur connaît-il vraiment les chiffres ?
4.4 Lorsque le processeur rencontre une instruction if
4.4.1 La naissance de la technologie des pipelines
__4.4.2 Processeur : Méga-usine et pipeline
4.4.3 Si le pipeline rencontre un pipeline
4.4.4 Prédiction de branchement : Faire en sorte que le processeur devine correctement autant que possible.
4.5 Quelle est la relation entre le nombre de cœurs du processeur et le nombre de threads ?
__4.5.1 Recettes et code, sautés et fils de discussion
4.5.2 Partitionnement du travail et blocage des E/S
4.5.3 Multicœur et multithreading
4.6 Évolution des processeurs (Partie 1) : La naissance des jeux d’instructions complexes
__4.6.1 Le processeur vu par les programmeurs
4.6.2 Capacités du processeur : Jeu d’instructions
4.6.3 Abstraction : Moins, c'est plus
4.6.4 Le code occupe également de l'espace de stockage
4.6.5 La naissance d'un jeu d'instructions complexe inévitable
4.6.6 Problèmes liés à la conception du microcode
4.7 Évolution des processeurs (2e partie) : La naissance du jeu d’instructions réduit
4.7.1 De la complexité à la simplicité
4.7.2 Philosophie de l'ensemble de commandes réduit
4.7.3 Différence entre les jeux d'instructions complexes et réduits
__4.7.4 Pipeline de commandes
4.7.5 Devenir mondialement connu
4.8 Évolution du processeur (Partie 2) : Contre-attaque en cas de crise
4.8.1 Si vous ne pouvez pas les battre, rejoignez-les : CISC, c'est la même chose que RISC
__4.8.2 L'hyperthreading est une technique redoutable
4.8.3 Tirer parti des points forts et compenser les faiblesses : Intégrer CISC et RISC
4.8.4 La technologie ne fait pas tout : la guerre commerciale entre CISC et RISC
4.9 Maîtriser le processeur, la pile et les appels de fonction, les appels système, le changement de thread et la gestion des interruptions
__4.9.1 Inscription
__4.9.2 Pointeur de pile
__4.9.3 Registre d'adresse d'instruction
__4.9.4 Registre d'état
4.9.5 Informations situationnelles
__4.9.6 Imbrication et piles
4.9.7 Appels de fonctions et pile d'exécution
__4.9.8 Appels système et pile d'état du noyau
4.9.9 Interruptions et pile de fonctions d'interruption
__4.9.10 Changement de thread et pile d'état du noyau
4.10 Résumé
Chapitre 5 : Obtenir de grands résultats avec de petites choses, l’argent
5.1 Cache, l'omniprésent
5.1.1 Différences de vitesse entre le processeur et la mémoire
5.1.2 Bibliothèque, Bureau, Cache
5.1.3 Rien n'est gratuit : actualisation du cache
5.1.4 Rien n'est gratuit : cohérence du cache multicœur
5.1.5 Utilisation de la mémoire comme cache disque
__5.1.6 Mémoire virtuelle et disques
__5.1.7 Comment le processeur lit-il la mémoire ?
5.1.8 Prise en charge du stockage distribué
5.2 Comment écrire des programmes compatibles avec le cache ?
5.2.1 Principe de localisation du programme
__5.2.2 Utilisation des pools de mémoire
__5.2.3 Relocalisation de la structure struct
5.2.4 Séparation des données chaudes et froides
__5.2.5 Structures de données optimisées pour le cache
5.2.6 Parcours d'un tableau multidimensionnel
5.3 Inhibiteurs de performance multithread
5.3.1 L'unité de base de l'interaction entre le cache et la mémoire : la ligne de cache
__5.3.2 Premier facteur de perte de performance : problèmes de rebond du cache
5.3.3 Deuxième facteur de dégradation des performances : le problème du faux partage
5.4 Le Bonghwaheejehu et la barrière de la mémoire
5.4.1 Exécution non séquentielle des instructions : Compilateurs et OoOE
5.4.2 Le cache doit également être pris en compte
5.4.3 Quatre types d'obstacles à la mémoire
5.4.4 Sémantique d'acquisition et de libération
__5.4.5 Interfaces fournies par C++
__5.4.6 Processeurs différents, natures différentes
5.4.7 Qui devrait se soucier du réordonnancement des instructions : Programmation sans verrouillage
5.4.8 Programmation avec et sans verrouillage
__5.4.9 Débat sur la réorganisation des commandes
5.5 Résumé
Chapitre 6 : Existe-t-il un ordinateur sans entrée/sortie ?
6.1 Comment le processeur gère-t-il les opérations d'entrée/sortie ?
6.1.1 Manipulation professionnelle : Instructions de la machine d’entrée/sortie
6.1.2 Mappage mémoire entrée/sortie
6.1.3 Nature du fonctionnement du processeur en lecture et en écriture du clavier
6.1.4 Sondage : Continuez à vérifier
6.1.5 Traitement des commandes et des annulations de livraison de repas
6.1.6 E/S pilotées par interruption
__6.1.7 Comment le processeur détecte-t-il les signaux d'interruption ?
6.1.8 Différence entre la gestion des interruptions et les appels de fonction
6.1.9 Sauvegarde et restauration de l'état d'exécution d'un programme suspendu
6.2 Que fait le processeur lorsque le disque gère les E/S ?
__6.2.1 Contrôleur de périphérique
__6.2.2 Le processeur doit-il copier les données directement ?
6.2.3 Accès direct à la mémoire
6.2.4 Résumé de l'ensemble du processus
6.2.5 Implications pour les programmeurs
6.3 Que se passe-t-il pour un programme lorsqu'il lit un fichier ?
6.3.1 Entrées/sorties du point de vue de la mémoire
__6.3.2 Comment la fonction read lit-elle un fichier ?
6.4 Le secret d'une forte concurrence : le multiplexage des E/S
__6.4.1 Descripteur de fichier
__6.4.2 Comment gérer efficacement plusieurs entrées et sorties ?
6.4.3 Me faire appeler à la place de l'autre personne
6.4.4 Multiplexage des entrées/sorties
6.4.5 Les Trois Mousquetaires : sélectionner, sondage, sondage électronique
6.5 mmap : Traitement des fichiers par lecture et écriture en mémoire
6.5.1 Fichiers et mémoire virtuelle
__6.5.2 Système d'exploitation Magician
__6.5.3 mmap vs. fonctions de lecture/écriture traditionnelles
6.5.4 Gestion des fichiers volumineux
6.5.5 Bibliothèques de liens dynamiques et mémoire partagée
__6.5.6 Manipulation directe de mmap
6.6 Quel sera le délai dans chaque partie d'un système informatique ?
__6.6.1 Convertir en indicateur de temps
6.6.2 Convertir en indicateur de distance
6.7 Résumé
1.1 Et si vous inventiez un langage de programmation ?
__1.1.1 Genèse : Le processeur est un idiot intelligent
__1.1.2 Le langage assembleur apparaît
1.1.3 Détails des couches de bas niveau vs abstractions des couches de haut niveau
__1.1.4 Règles complètes : Le début d’un langage de programmation de haut niveau
__1.1.5 Inception et récursivité : l’essence du code
__1.1.6 Faire comprendre la récursivité aux ordinateurs
__1.1.7 Excellent traducteur : Compilateur
__1.1.8 La naissance des langues interprétées
1.2 Comment fonctionne un compilateur ?
__1.2.1 Le compilateur est un programme normal, rien de spécial.
__1.2.2 Extraction de chaque jeton
1.2.3 Ce que le jeton tente d'exprimer
__1.2.4 Existe-t-il des anomalies dans l'arbre syntaxique généré ?
1.2.5 Génération de code intermédiaire à partir d'arbres syntaxiques
__1.2.6 Génération de code
1.3 Le secret inavouable du Linker
__1.3.1 Voici comment fonctionne l'éditeur de liens
1.3.2 Interprétation des symboles : Offre et demande
__1.3.3 Bibliothèques statiques, bibliothèques dynamiques et exécutables
1.3.4 Avantages et inconvénients des bibliothèques dynamiques
1.3.5 Relocalisation : Détermination de l'adresse d'un symbole au moment de l'exécution
1.3.6 Structure de la mémoire virtuelle et de la mémoire programme
1.4 Pourquoi l'abstraction est importante en informatique
__1.4.1 Programmation et abstraction
__1.4.2 Conception et abstraction du système
1.5 Résumé
Chapitre 2 Le programme s'est exécuté, mais je ne sais pas ce qui se passe.
2.1 Comprendre les principes fondamentaux des systèmes d'exploitation, des processus et des threads
2.1.1 Tout commence avec le processeur
2.1.2 Du processeur au système d'exploitation
__2.1.3 Le processus est très bon, mais reste néanmoins peu pratique.
__2.1.4 Évolution des processus vers les threads
__2.1.5 Multithreading et structure de la mémoire
__2.1.6 Exemple d'utilisation des threads
__2.1.7 Fonctionnement du pool de threads
__2.1.8 Nombre de threads dans le pool de threads
2.2 Ressources de processus partagées entre les threads
__2.2.1 Ressources réservées aux threads
__2.2.2 Zone de code : Toutes les fonctions peuvent être placées dans des threads et exécutées.
__2.2.3 Zone de données : Tous les threads peuvent accéder aux variables de la zone de données.
__2.2.4 Zone du tas : les pointeurs sont essentiels
__2.2.5 Zone de pile : Données privées au sein d’un espace partagé
__2.2.6 Bibliothèques de liens dynamiques et fichiers
__2.2.7 Stockage réservé aux threads
2.3 Comment dois-je écrire exactement du code thread-safe ?
__2.3.1 Liberté et contraintes
__2.3.2 Qu'est-ce que la sécurité des fils ?
__2.3.3 Ressources spécifiques au thread et partagées
__2.3.4 Utiliser uniquement les ressources spécifiques au thread
__2.3.5 Ressources spécifiques au thread et paramètres de fonction
__2.3.6 Utilisation des variables globales
__2.3.7 Stockage réservé aux threads
__2.3.8 Valeurs de retour de la fonction
__2.3.9 Appel de code non thread-safe
__2.3.10 Comment implémenter du code thread-safe ?
2.4 Comment les programmeurs doivent-ils comprendre les coroutines ?
__2.4.1 Fonctions générales
__2.4.2 Des fonctions régulières aux coroutines
__2.4.3 Explication intuitive des coroutines
__2.4.4 Les fonctions ne sont qu'un cas particulier de coroutines
__2.4.5 Historique des coroutines
__2.4.6 Comment les coroutines sont-elles implémentées ?
2.5 Comprendre parfaitement les fonctions de rappel
__2.5.1 Tout commence par l'exigence suivante :
2.5.2 Pourquoi les rappels sont nécessaires
__2.5.3 Rappels asynchrones
__2.5.4 Les rappels asynchrones ouvrent la voie à une nouvelle approche de la programmation
__2.5.5 Définition de la fonction de rappel
__2.5.6 Deux types de rappel
__2.5.7 Le problème des rappels asynchrones : l’enfer des rappels
2.6 Comprendre parfaitement les concepts synchrones et asynchrones
__2.6.1 Programmeur travailleur
__2.6.2 Passer des appels téléphoniques et envoyer des courriels
__2.6.3 Appel synchrone
__2.6.4 Appels asynchrones
__2.6.5 Opérations synchrones et asynchrones sur les serveurs Web
2.7 Ah oui ! Il existe des modes bloquants et non bloquants.
__2.7.1 Blocage et non-blocage
2.7.2 Le problème fondamental du blocage : E/S
2.7.3 E/S non bloquantes et asynchrones
2.7.4 Analogie avec la commande d'une pizza
__2.7.5 Motivation et blocage
__2.7.6 Asynchrone et non bloquant
2.8 Mise en œuvre d'un serveur à haute concurrence et hautes performances
__2.8.1 Multitraitement
__2.8.2 Multithreading
__2.8.3 Bouclage d'événements et pilotage par événements
__2.8.4 Premier problème : Sources d’événements et multiplexage des E/S
__2.8.5 Deuxième problème : Boucles d’événements et multithreading
__2.8.6 Fonctionnement d'un café : le modèle du répondant
__2.8.7 Cycle d'événements et entrées/sorties
__2.8.8 Fonctions asynchrones et de rappel
__2.8.9 Coroutines : Programmation asynchrone avec des méthodes synchrones
__2.8.10 Processeur, Threads, Coroutines
2.9 Parcours d'un système informatique : des données, du code, des rappels et des fermetures aux conteneurs et aux machines virtuelles
__2.9.1 Code, données, variables, pointeurs
__2.9.2 Fonctions de rappel et fermetures
__2.9.3 Technologie des conteneurs et des machines virtuelles
2.10 Résumé
Chapitre 3 : Hiérarchies de bas niveau ? Commençons par le casier appelé mémoire.
3.1 La nature de la mémoire, des pointeurs et des références
__3.1.1 Quelle est la nature de la mémoire ? Casiers, bits, octets et objets.
3.1.2 De la mémoire aux variables : que signifient les variables ?
3.1.3 Des variables aux pointeurs : Comprendre les pointeurs
__3.1.4 Le pouvoir et la destruction des pointeurs : capacités et responsabilités
3.1.5 Du pointeur à la référence : masquage des adresses mémoire
3.2 À quoi ressemble un processus en mémoire ?
3.2.1 Mémoire virtuelle : ce que vous voyez n’est pas toujours ce que vous obtenez
3.2.2 Pages et tables de pages : du virtuel au réel
3.3 Zone de pile : Comment les appels de fonction sont-ils implémentés ?
__3.3.1 Outils pour programmeurs : Fonctions
3.3.2 Suivi de l'activité d'appel de fonction : Pile
3.3.3 Cadres et zones de pile : une perspective macro
__3.3.4 Comment les sauts et les retours de fonction sont-ils implémentés ?
__3.3.5 Comment le passage des paramètres et les valeurs de retour sont-ils implémentés ?
__3.3.6 Où sont les variables locales ?
__3.3.7 Sauvegarde et restauration des registres
__3.3.8 Dressons un tableau d'ensemble, où en sommes-nous maintenant ?
3.4 Zone de tas : Comment l'allocation dynamique de mémoire est-elle implémentée ?
3.4.1 Pourquoi avons-nous besoin d'espace mémoire ?
3.4.2 Implémentation directe de l'allocateur de mémoire malloc
3.4.3 Du parking à la gestion de la mémoire
3.4.4 Gestion des fragments de mémoire libre
3.4.5 Suivi de l'état d'allocation de mémoire
3.4.6 Comment choisir une zone de mémoire libre : stratégie d’allocation
3.4.7 Allocation de mémoire
3.4.8 Libération de la mémoire
3.4.9 Fusion efficace des fragments de mémoire libre
3.5 Que se passe-t-il au niveau le plus bas lors de l'allocation de mémoire ?
__3.5.1 État d'exécution du processeur Ciel, Terre et Humain
3.5.2 État du noyau et état de l'utilisateur
__3.5.3 Portail : Appels système
__3.5.4 Bibliothèque standard : Masquer les différences entre les systèmes
3.5.5 Lorsque la zone de tas est saturée en mémoire
__3.5.6 Demande de mémoire au système d'exploitation : brk
__3.5.7 Sous l'iceberg : la mémoire virtuelle est le boss final
3.5.8 L'histoire complète de l'allocation de mémoire
3.6 Comment le pool de mémoire est-il implémenté pour les serveurs hautes performances ?
3.6.1 Pools de mémoire vs. allocateurs de mémoire à usage général
3.6.2 Principes de la technologie de pool de mémoire
3.6.3 Implémentation d'un pool de mémoire très simple
3.6.4 Implémentation d'un pool de mémoire légèrement plus complexe
__3.6.5 Problèmes de sécurité des threads avec les pools de mémoire
3.7 Bogues courants liés à la mémoire
3.7.1 Retourner un pointeur vers une variable locale
3.7.2 Mauvaise compréhension de l'arithmétique des pointeurs
__3.7.3 Déréférencement d'un pointeur problématique
3.7.4 Lecture de la mémoire non initialisée
3.7.5 Référencement d'une mémoire déjà libérée
__3.7.6 Les indices des tableaux commencent à 0
__3.7.7 Stack Overflow
__3.7.8 Fuite de mémoire
3.8 Pourquoi les SSD ne peuvent-ils pas être utilisés comme mémoire ?
3.8.1 Différence entre la lecture/écriture en mémoire et la lecture/écriture sur disque
__3.8.2 Limites de mémoire virtuelle
__3.8.3 Problèmes liés à la durée de vie des SSD
3.9 Résumé
Chapitre 4 : Des transistors aux processeurs : Rien n'est plus important que cela.
4.1 Ce petit jouet s'appelle un CPU.
4.1.1 Grande invention
4.1.2 Conjonction logique, conjonction logique et négation logique
__4.1.3 Le Tao donne naissance à un, un donne naissance à deux, deux donne naissance à trois, et trois donne naissance à toutes choses.
__4.1.4 D’où provient la puissance de calcul ?
4.1.5 Capacité de mémorisation exceptionnelle
4.1.6 La naissance des registres et de la mémoire
4.1.7 Matériel ou logiciel ? Appareils à usage général
4.1.8 Technologie matérielle de base : Instructions machine
4.1.9 Interface logiciel-matériel : Jeu de commandes
4.1.10 Les circuits nécessitent des conducteurs
__4.1.11 Une grande réussite, le processeur est né !
4.2 Que fait le processeur lorsqu'il est inactif ?
__4.2.1 Quel est le taux d'utilisation du processeur de votre ordinateur ?
4.2.2 Gestion et planification des processus
4.2.3 Vérification de l'état de la file d'attente : une meilleure conception
4.2.4 Tout retourne au processeur
4.2.5 Processus inactifs et états de faible consommation du processeur
__4.2.6 Rompre la boucle infinie : les interruptions
4.3 Comment le processeur reconnaît-il les nombres ?
__4.3.1 Le nombre 0 et les entiers positifs
__4.3.2 Entiers signés
4.3.3 Ajouter un signe moins à un nombre positif donne immédiatement le nombre négatif correspondant : représentation signe-magnitude
4.3.4 Inversion de la représentation signe-magnitude : complément à 1
4.3.5 Addition de deux nombres qui ne sont pas simples
4.3.6 Représentation conviviale pour ordinateur : le complément à deux
__4.3.7 Le processeur connaît-il vraiment les chiffres ?
4.4 Lorsque le processeur rencontre une instruction if
4.4.1 La naissance de la technologie des pipelines
__4.4.2 Processeur : Méga-usine et pipeline
4.4.3 Si le pipeline rencontre un pipeline
4.4.4 Prédiction de branchement : Faire en sorte que le processeur devine correctement autant que possible.
4.5 Quelle est la relation entre le nombre de cœurs du processeur et le nombre de threads ?
__4.5.1 Recettes et code, sautés et fils de discussion
4.5.2 Partitionnement du travail et blocage des E/S
4.5.3 Multicœur et multithreading
4.6 Évolution des processeurs (Partie 1) : La naissance des jeux d’instructions complexes
__4.6.1 Le processeur vu par les programmeurs
4.6.2 Capacités du processeur : Jeu d’instructions
4.6.3 Abstraction : Moins, c'est plus
4.6.4 Le code occupe également de l'espace de stockage
4.6.5 La naissance d'un jeu d'instructions complexe inévitable
4.6.6 Problèmes liés à la conception du microcode
4.7 Évolution des processeurs (2e partie) : La naissance du jeu d’instructions réduit
4.7.1 De la complexité à la simplicité
4.7.2 Philosophie de l'ensemble de commandes réduit
4.7.3 Différence entre les jeux d'instructions complexes et réduits
__4.7.4 Pipeline de commandes
4.7.5 Devenir mondialement connu
4.8 Évolution du processeur (Partie 2) : Contre-attaque en cas de crise
4.8.1 Si vous ne pouvez pas les battre, rejoignez-les : CISC, c'est la même chose que RISC
__4.8.2 L'hyperthreading est une technique redoutable
4.8.3 Tirer parti des points forts et compenser les faiblesses : Intégrer CISC et RISC
4.8.4 La technologie ne fait pas tout : la guerre commerciale entre CISC et RISC
4.9 Maîtriser le processeur, la pile et les appels de fonction, les appels système, le changement de thread et la gestion des interruptions
__4.9.1 Inscription
__4.9.2 Pointeur de pile
__4.9.3 Registre d'adresse d'instruction
__4.9.4 Registre d'état
4.9.5 Informations situationnelles
__4.9.6 Imbrication et piles
4.9.7 Appels de fonctions et pile d'exécution
__4.9.8 Appels système et pile d'état du noyau
4.9.9 Interruptions et pile de fonctions d'interruption
__4.9.10 Changement de thread et pile d'état du noyau
4.10 Résumé
Chapitre 5 : Obtenir de grands résultats avec de petites choses, l’argent
5.1 Cache, l'omniprésent
5.1.1 Différences de vitesse entre le processeur et la mémoire
5.1.2 Bibliothèque, Bureau, Cache
5.1.3 Rien n'est gratuit : actualisation du cache
5.1.4 Rien n'est gratuit : cohérence du cache multicœur
5.1.5 Utilisation de la mémoire comme cache disque
__5.1.6 Mémoire virtuelle et disques
__5.1.7 Comment le processeur lit-il la mémoire ?
5.1.8 Prise en charge du stockage distribué
5.2 Comment écrire des programmes compatibles avec le cache ?
5.2.1 Principe de localisation du programme
__5.2.2 Utilisation des pools de mémoire
__5.2.3 Relocalisation de la structure struct
5.2.4 Séparation des données chaudes et froides
__5.2.5 Structures de données optimisées pour le cache
5.2.6 Parcours d'un tableau multidimensionnel
5.3 Inhibiteurs de performance multithread
5.3.1 L'unité de base de l'interaction entre le cache et la mémoire : la ligne de cache
__5.3.2 Premier facteur de perte de performance : problèmes de rebond du cache
5.3.3 Deuxième facteur de dégradation des performances : le problème du faux partage
5.4 Le Bonghwaheejehu et la barrière de la mémoire
5.4.1 Exécution non séquentielle des instructions : Compilateurs et OoOE
5.4.2 Le cache doit également être pris en compte
5.4.3 Quatre types d'obstacles à la mémoire
5.4.4 Sémantique d'acquisition et de libération
__5.4.5 Interfaces fournies par C++
__5.4.6 Processeurs différents, natures différentes
5.4.7 Qui devrait se soucier du réordonnancement des instructions : Programmation sans verrouillage
5.4.8 Programmation avec et sans verrouillage
__5.4.9 Débat sur la réorganisation des commandes
5.5 Résumé
Chapitre 6 : Existe-t-il un ordinateur sans entrée/sortie ?
6.1 Comment le processeur gère-t-il les opérations d'entrée/sortie ?
6.1.1 Manipulation professionnelle : Instructions de la machine d’entrée/sortie
6.1.2 Mappage mémoire entrée/sortie
6.1.3 Nature du fonctionnement du processeur en lecture et en écriture du clavier
6.1.4 Sondage : Continuez à vérifier
6.1.5 Traitement des commandes et des annulations de livraison de repas
6.1.6 E/S pilotées par interruption
__6.1.7 Comment le processeur détecte-t-il les signaux d'interruption ?
6.1.8 Différence entre la gestion des interruptions et les appels de fonction
6.1.9 Sauvegarde et restauration de l'état d'exécution d'un programme suspendu
6.2 Que fait le processeur lorsque le disque gère les E/S ?
__6.2.1 Contrôleur de périphérique
__6.2.2 Le processeur doit-il copier les données directement ?
6.2.3 Accès direct à la mémoire
6.2.4 Résumé de l'ensemble du processus
6.2.5 Implications pour les programmeurs
6.3 Que se passe-t-il pour un programme lorsqu'il lit un fichier ?
6.3.1 Entrées/sorties du point de vue de la mémoire
__6.3.2 Comment la fonction read lit-elle un fichier ?
6.4 Le secret d'une forte concurrence : le multiplexage des E/S
__6.4.1 Descripteur de fichier
__6.4.2 Comment gérer efficacement plusieurs entrées et sorties ?
6.4.3 Me faire appeler à la place de l'autre personne
6.4.4 Multiplexage des entrées/sorties
6.4.5 Les Trois Mousquetaires : sélectionner, sondage, sondage électronique
6.5 mmap : Traitement des fichiers par lecture et écriture en mémoire
6.5.1 Fichiers et mémoire virtuelle
__6.5.2 Système d'exploitation Magician
__6.5.3 mmap vs. fonctions de lecture/écriture traditionnelles
6.5.4 Gestion des fichiers volumineux
6.5.5 Bibliothèques de liens dynamiques et mémoire partagée
__6.5.6 Manipulation directe de mmap
6.6 Quel sera le délai dans chaque partie d'un système informatique ?
__6.6.1 Convertir en indicateur de temps
6.6.2 Convertir en indicateur de distance
6.7 Résumé
Image détaillée

Dans le livre
En 1984, lorsque j'ai commencé à programmer, les ordinateurs 8 bits commençaient tout juste à arriver sur le marché coréen, mais en réalité, aux États-Unis, le 80386 était déjà en plein développement après le 80286.
On peut donc affirmer sans risque d'erreur que l'écart entre le marché informatique national et le marché informatique étranger était alors largement supérieur à 10 ans.
Comme je l'explique également dans ce livre, à l'époque, la programmation était un domaine accessible seulement à un très petit nombre de personnes, et la conception et la structure du matériel étaient, bien entendu, une connaissance approfondie.
Ainsi, même s'il était extrêmement difficile de trouver des documents connexes, c'était une époque où je devais me procurer des livres étrangers un par un par divers canaux ou en faire des copies et les diffuser.
L'un des livres étrangers que je possédais à l'époque était Inside the IBM PC de Peter Norton, connu pour les utilitaires Norton.
Ce livre explique en détail comment le PC, autrefois considéré comme une machine étrange, est structuré, quel processus interne suivent les frappes au clavier avant d'être affichées à l'écran, et ce qui se passe en interne entre-temps.
Étonnamment, j'ai encore ce livre.
Même maintenant, il m'arrive de le ressortir et de le lire.
C'est un livre tellement amusant, et on y découvre de nouvelles choses à chaque fois qu'on le lit.
On a l'impression de répéter sans cesse la même histoire, mais il y a 30 ans, utiliser un ordinateur et programmer étaient pratiquement synonymes.
Ainsi, chaque utilisateur d'ordinateur était un développeur potentiel de logiciels et de matériel.
De nos jours, nous vivons dans un monde où les gens n'ont peut-être pas de télévision à la maison, mais ils possèdent au moins quelques ordinateurs.
La plupart des utilisateurs d'ordinateurs mènent une vie qui n'a rien à voir avec la programmation.
Mais si vous tenez ce livre entre vos mains, vous avez assurément déjà fait un pas dans le monde de la programmation.
Ainsi, plutôt que de me contenter des quelques lignes de code qui s'exécutent sans erreur, je pense que réfléchir à ce qui se passe à l'intérieur et à son impact sur mon code m'a offert une opportunité de développement supplémentaire.
Je suis fier de dire que ce livre est l'un des rares qui peuvent vous aider à faire le premier pas vers ce type de développement.
Ce livre offre une approche systématique et une compréhension conceptuelle à ceux d'entre vous qui sont lassés de parcourir des informations éparpillées sur Internet ; il sert également de guide et éveille la curiosité pour un monde que vous n'avez jamais connu auparavant.
Si ce livre peut vous aider à écrire un code ne serait-ce qu'un peu meilleur et plus pertinent, ce sera une grande récompense pour moi, qui ai travaillé si dur à sa traduction.
On peut donc affirmer sans risque d'erreur que l'écart entre le marché informatique national et le marché informatique étranger était alors largement supérieur à 10 ans.
Comme je l'explique également dans ce livre, à l'époque, la programmation était un domaine accessible seulement à un très petit nombre de personnes, et la conception et la structure du matériel étaient, bien entendu, une connaissance approfondie.
Ainsi, même s'il était extrêmement difficile de trouver des documents connexes, c'était une époque où je devais me procurer des livres étrangers un par un par divers canaux ou en faire des copies et les diffuser.
L'un des livres étrangers que je possédais à l'époque était Inside the IBM PC de Peter Norton, connu pour les utilitaires Norton.
Ce livre explique en détail comment le PC, autrefois considéré comme une machine étrange, est structuré, quel processus interne suivent les frappes au clavier avant d'être affichées à l'écran, et ce qui se passe en interne entre-temps.
Étonnamment, j'ai encore ce livre.
Même maintenant, il m'arrive de le ressortir et de le lire.
C'est un livre tellement amusant, et on y découvre de nouvelles choses à chaque fois qu'on le lit.
On a l'impression de répéter sans cesse la même histoire, mais il y a 30 ans, utiliser un ordinateur et programmer étaient pratiquement synonymes.
Ainsi, chaque utilisateur d'ordinateur était un développeur potentiel de logiciels et de matériel.
De nos jours, nous vivons dans un monde où les gens n'ont peut-être pas de télévision à la maison, mais ils possèdent au moins quelques ordinateurs.
La plupart des utilisateurs d'ordinateurs mènent une vie qui n'a rien à voir avec la programmation.
Mais si vous tenez ce livre entre vos mains, vous avez assurément déjà fait un pas dans le monde de la programmation.
Ainsi, plutôt que de me contenter des quelques lignes de code qui s'exécutent sans erreur, je pense que réfléchir à ce qui se passe à l'intérieur et à son impact sur mon code m'a offert une opportunité de développement supplémentaire.
Je suis fier de dire que ce livre est l'un des rares qui peuvent vous aider à faire le premier pas vers ce type de développement.
Ce livre offre une approche systématique et une compréhension conceptuelle à ceux d'entre vous qui sont lassés de parcourir des informations éparpillées sur Internet ; il sert également de guide et éveille la curiosité pour un monde que vous n'avez jamais connu auparavant.
Si ce livre peut vous aider à écrire un code ne serait-ce qu'un peu meilleur et plus pertinent, ce sera une grande récompense pour moi, qui ai travaillé si dur à sa traduction.
--- Note du traducteur
Avis de l'éditeur
Facile à apprendre grâce aux analogies et aux images
L'essence des systèmes informatiques
Comprendre le fonctionnement interne d'un ordinateur permet de modifier son code.
Une compréhension approfondie des principes et des mécanismes des systèmes informatiques peut améliorer la lisibilité et la maintenabilité du code que vous écrivez.
De plus, il permet d'optimiser efficacement les performances des programmes et de détecter et résoudre rapidement les erreurs d'exécution de code ou les comportements anormaux du système.
Acquérir une compréhension approfondie des principes des systèmes informatiques.
Nous allons disséquer la structure d'un système informatique, qui est abstraite couche par couche, une par une, en commençant par les langages de programmation et les compilateurs, puis en apprenant le système d'exploitation, les processus, les threads et les coroutines, la synchronisation et la mémoire.
Vous découvrirez également les principes de mise en œuvre des processeurs, des caches, des entrées/sorties, des systèmes de fichiers, des réseaux et des communications, de la sécurité et du chiffrement, ainsi que du calcul parallèle.
L'essence des systèmes informatiques
Comprendre le fonctionnement interne d'un ordinateur permet de modifier son code.
Une compréhension approfondie des principes et des mécanismes des systèmes informatiques peut améliorer la lisibilité et la maintenabilité du code que vous écrivez.
De plus, il permet d'optimiser efficacement les performances des programmes et de détecter et résoudre rapidement les erreurs d'exécution de code ou les comportements anormaux du système.
Acquérir une compréhension approfondie des principes des systèmes informatiques.
Nous allons disséquer la structure d'un système informatique, qui est abstraite couche par couche, une par une, en commençant par les langages de programmation et les compilateurs, puis en apprenant le système d'exploitation, les processus, les threads et les coroutines, la synchronisation et la mémoire.
Vous découvrirez également les principes de mise en œuvre des processeurs, des caches, des entrées/sorties, des systèmes de fichiers, des réseaux et des communications, de la sécurité et du chiffrement, ainsi que du calcul parallèle.
SPÉCIFICATIONS DES PRODUITS
- Date d'émission : 11 mars 2024
Nombre de pages, poids, dimensions : 480 pages | 858 g | 183 × 235 × 20 mm
- ISBN13 : 9791140708819
Vous aimerez peut-être aussi
카테고리
Langue coréenne
Langue coréenne