Comment fonctionnent les ordinateurs : une explication par la base


En commençant par une pression de touche

Vous appuyez sur la lettre ‘A’ de votre clavier.

En moins d’une milliseconde, le caractère apparaît à l’écran.

Cela semble simple ? En réalité, dans cette milliseconde, un signal électrique traverse au moins 6 couches d’abstraction, passe par des dizaines de composants matériels et franchit plusieurs bus pour accomplir cette interaction “simple”.

L’essence des ordinateurs n’est pas le calcul, mais l’abstraction.

Chaque couche cache la complexité sous-jacente et n’expose qu’une interface propre à la couche supérieure. C’est grâce à ces abstractions que les programmeurs peuvent écrire du code dans des langages de haut niveau sans se soucier de la façon dont les électrons circulent à travers les transistors.

Aujourd’hui, nous retraçons le voyage complet d’un signal de pression de touche, en voyant comment les ordinateurs, couche après couche d’abstraction, transforment une action physique en un caractère à l’écran.

Première couche : du signal physique au code de balayage

Image

Ce que vous pressez n’est pas une lettre, mais un interrupteur.

Sous chaque touche du clavier se trouve un interrupteur mécanique. Lorsque vous appuyez sur la touche ‘A’, l’interrupteur se ferme et le courant circule. C’est la réalité physique la plus fondamentale — seulement marche et arrêt, pas de ‘A’.

Le travail du contrôleur de clavier est de traduire ce signal physique en nombres que l’ordinateur peut comprendre.

Comment fait-il cela ?

Balayage matriciel

Plus de 100 touches sur un clavier. Si chacune avait son propre fil connecté à l’ordinateur, le câble du clavier serait plus épais que votre doigt. Le clavier utilise donc une conception intelligente : le balayage matriciel.

Imaginez un échiquier, avec des lignes de rangées et des lignes de colonnes qui se croisent. Chaque touche se trouve à une intersection. Le contrôleur alimente rapidement chaque rangée et détecte s’il y a du courant sur chaque colonne. Si la colonne 5 détecte du courant lorsque la rangée 3 est alimentée, cela signifie que la touche à la rangée 3, colonne 5 a été pressée.

C’est de là que vient le code de balayage (scan code) — un nombre qui représente la position d’une touche.

Appuyer sur ‘A’ pourrait produire le code de balayage 0x1E. Relâcher ‘A’ produit 0x9E (avec un bit haut supplémentaire indiquant “relâchement”).

Première couche terminée : action physique → codage numérique.

Mais ce n’est pas fini. Le code de balayage est encore dans le tampon interne du clavier, attendant d’être envoyé.

Deuxième couche : du périphérique d’E/S à la mémoire

Image

Le code de balayage doit atteindre le CPU, mais le CPU ne peut pas rester à attendre une entrée clavier.

Le CPU fonctionne à des milliards d’opérations par seconde ; les entrées clavier arrivent à des dizaines d’entrées par seconde. Si le CPU vérifiait “y a-t-il une entrée clavier ?” avant chaque instruction, 99,9999 % de son temps serait gaspillé.

Quelle est la solution ? Le mécanisme d’interruption.

Interruptions : la version matérielle de “appelez-moi quand vous êtes prêt”

La philosophie de conception des interruptions reflète la vie quotidienne : vous n’appelez pas le livreur toutes les 5 minutes pour demander “mon colis est-il arrivé ?” Au lieu de cela, le livreur vous appelle quand il arrive.

Après que le contrôleur de clavier a généré un code de balayage, il envoie un signal de demande d’interruption (IRQ) au CPU.

Ce signal passe par le contrôleur d’interruptions (8259A ou son équivalent moderne) et se voit attribuer un numéro d’interruption. Le clavier est généralement IRQ1, numéro d’interruption 0x21.

Après avoir exécuté chaque instruction, le CPU vérifie s’il y a des signaux d’interruption. S’il y en a un, il suspend son travail en cours et traite l’interruption.

La table des vecteurs d’interruption

Comment le CPU sait-il comment traiter une interruption du clavier ?

En mémoire, il y a une table des vecteurs d’interruption (Interrupt Vector Table) qui stocke l’adresse du gestionnaire pour chaque numéro d’interruption. C’est comme un annuaire téléphonique : le numéro d’interruption 0x21 correspond à l’adresse du gestionnaire de clavier.

Lorsque le CPU reçoit une interruption du clavier :

  1. Il empile le compteur de programme (PC), le registre d’état, etc.
  2. Il consulte la table avec le numéro d’interruption pour trouver l’adresse du gestionnaire
  3. Il saute vers le gestionnaire et l’exécute

Le gestionnaire de clavier lit le code de balayage via un port d’E/S (généralement 0x60), puis le stocke dans le tampon clavier en mémoire.

Deuxième couche terminée : événement d’E/S → données en mémoire.

Maintenant, le code de balayage est stocké en mémoire. Mais c’est encore un code de balayage, pas le caractère ‘A’.

Troisième couche : du code de balayage au caractère

Image

Le code de balayage 0x1E représente “la position de la touche A sur le clavier”, pas le caractère ‘A’.

Pourquoi ? Parce que la même touche peut représenter différents caractères sur les claviers de différents pays. Les Américains appuient dessus et obtiennent ‘A’ ; les Français appuient dessus et obtiennent ‘Q’ (la disposition de leur clavier est différente).

Le système d’exploitation est responsable de la conversion des codes de balayage en caractères.

Le sous-système d’entrée

Les systèmes d’exploitation modernes ont tous un sous-système d’entrée (Input Subsystem), qui gère :

  1. La lecture des codes de balayage depuis le tampon du noyau
  2. Leur conversion en caractères selon la disposition actuelle du clavier
  3. La gestion des touches modificatrices (Shift+A = ‘A’ majuscule, Ctrl+C = commande copier)
  4. La livraison du caractère à la fenêtre active

Cette conversion implique une table de correspondance de disposition de clavier. Le registre Windows contient HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts, qui stocke les correspondances pour différentes langues.

Après la conversion, le caractère ‘A’ est placé dans une file de messages, en attendant d’être lu par l’application.

Troisième couche terminée : codage dépendant du matériel → codage unifié des caractères.

Quatrième couche : du caractère au pixel

Image

L’application reçoit le caractère ‘A’ et doit l’afficher à l’écran.

Mais ce que vous voyez n’est pas un caractère — ce sont des pixels.

Un moniteur ne comprend que les pixels — de quelle couleur chaque point est. Le caractère ‘A’ est un motif composé d’un ensemble de pixels, stocké dans un fichier de police.

Rendu des polices

Lorsque vous tapez ‘A’, l’application va :

  1. Chercher le fichier de police (ex. Microsoft YaHei, SimSun)
  2. Obtenir la description du glyphe pour ‘A’ (courbes vectorielles ou bitmap)
  3. Mettre à l’échelle le glyphe selon la taille de police
  4. Rastériser : convertir les courbes vectorielles en grille de pixels
  5. Appliquer l’anti-crénelage pour des bords plus lisses

Ces données de pixels sont écrites dans la mémoire vidéo (VRAM), c’est-à-dire la mémoire sur la carte graphique.

De la VRAM à l’écran

Le contrôleur d’affichage sur la carte graphique lit les données de la VRAM 60 fois par seconde (60 Hz), les convertit en signal vidéo et les envoie au moniteur.

Le moniteur reçoit le signal, contrôle la couleur de chaque pixel, et vous voyez le caractère ‘A’.

Quatrième couche terminée : codage de caractères → matrice de pixels.

Cinquième couche : comment le CPU exécute ces instructions

Image

Toutes les opérations mentionnées ci-dessus — balayage, interruptions, conversion, rendu — doivent finalement être exécutées par le CPU.

Comment le CPU exécute-t-il les instructions ?

Le cycle d’instruction : chercher-décoder-exécuter

L’exécution d’une instruction comporte trois étapes :

  1. Chercher (Fetch)

    • Le compteur de programme (PC) stocke l’adresse de la prochaine instruction
    • Envoyer l’adresse à la mémoire, récupérer l’instruction
    • Stocker l’instruction dans le registre d’instruction (IR)
  2. Décoder (Decode)

    • L’unité de contrôle analyse le code opération de l’instruction
    • Détermine quelle opération effectuer (addition ? chargement ? saut ?)
    • Détermine où se trouvent les opérandes
  3. Exécuter (Execute)

    • L’unité arithmétique et logique (UAL) effectue le calcul
    • Ou accède à la mémoire pour lire/écrire des données
    • Met à jour le compteur de programme

Puis on répète.

Un exemple

Supposons que le CPU doive exécuter ADD R1, R2, R3 (additionner les valeurs dans R2 et R3, stocker dans R1) :

  1. Chercher : lire le code machine pour cette instruction depuis la mémoire
  2. Décoder : reconnaître qu’il s’agit d’une instruction d’addition, opérandes dans R2 et R3
  3. Exécuter : l’UAL envoie les valeurs de R2 et R3 à l’additionneur, écrit le résultat dans R1

Chaque instruction se termine en nanosecondes.

Cinquième couche terminée : langage de haut niveau → instructions machine → signaux électriques.

Le coût de l’abstraction

L’abstraction n’est pas gratuite.

Chaque couche d’abstraction a un coût en performance :

  • Balayage du clavier : quelques microsecondes
  • Gestion d’interruption : des dizaines de microsecondes
  • Conversion du système d’exploitation : des centaines de microsecondes
  • Rendu des polices : quelques millisecondes
  • Écriture en VRAM : quelques microsecondes

Ensemble, cela constitue la “latence d’entrée” (input lag) que vous ressentez, généralement entre 10 et 50 millisecondes.

Pour une personne ordinaire, ce délai est négligeable. Mais pour les joueurs d’e-sport, c’est une différence de vie ou de mort. C’est pourquoi ils utilisent des claviers mécaniques (activation plus rapide), des moniteurs à taux de rafraîchissement élevé (144 Hz et plus) et des connexions filaires (le sans-fil ajoute une latence supplémentaire).

Une conclusion

L’essence des ordinateurs est l’abstraction : encapsuler la complexité, n’exposer qu’une interface simple.

Le voyage d’un signal de pression de touche :

Interrupteur physique → code de balayage → interruption → tampon mémoire → codage de caractères → file de messages → rendu de police → VRAM → pixel

Chaque couche ne fait qu’une chose : recevoir la sortie simplifiée de la couche inférieure, la traiter et fournir une interface simplifiée à la couche supérieure.

C’est précisément cette abstraction en couches qui permet aux humains de maîtriser des systèmes informatiques incroyablement complexes.

Les programmeurs n’ont pas besoin de savoir comment fonctionne le balayage du clavier — ils ont seulement besoin de lire la valeur de retour de getchar().

Les programmeurs n’ont pas besoin de savoir comment la carte graphique effectue le rendu — ils ont seulement besoin d’appeler la fonction DrawText().

La puissance de l’abstraction est de rendre la complexité gérable.

Image