Éclaircissement de la procédure d'arrêt

Le livre "Comment fonctionne Linux" indique que la procédure d'arrêt générale (indépendante du système d'initialisation) est quelque chose comme ceci:

  1. init request à chaque process de s'arrêter proprement.
  2. Si un process ne répond pas après un certain time, init le tue, en essayant d'abord un signal TERM.
  3. Si le signal TERM ne fonctionne pas, init utilise le signal KILL sur tous les retardataires.
  4. Le système verrouille les files système et met en place d'autres préparatifs pour l'arrêt.
  5. Le système démonte tous les filesystems autres que la racine.
  6. Le système restaure le système de files racine en lecture seule .
  7. Le système écrit toutes datatables mises en memory tampon dans le système de files avec le programme de synchronisation.
  8. La dernière étape consiste à dire au kernel de redémarrer ou de s'arrêter avec l'appel système reboot (2). Cela peut être fait par init ou un programme auxiliaire tel que reboot, stop ou poweroff.

Comment sync peut-il écrire ses tampons si le système de files est en lecture seule?

Vous avez raison d'être surpris: cet ordre n'a pas de sens. Si un livre le présente de cette façon, il est bâkey et trompeur.

Démonter un système de files ou le monter en lecture seule, écrit toutes datatables sur le disque. Lorsque la command umount ou mount -o remount,ro renvoie, toutes datatables sont écrites sur le disque et la sync n'a plus rien à faire. Il est inutile d'appeler sync avant (datatables seront écrites par l'opération umount de toute façon) et inutile de l'appeler après (il ne fera rien).

Je pense que ce n'était pas vrai dans certains anciens systèmes Unix, où il fallait appeler sync avant de démonter. L'appeler après était encore inutile.

Si vous regardez au-delà des filesystems, il peut y avoir des cas où la sync fait quelque chose. Par exemple, je pense que sur Linux sync , les métadonnées des baies RAID sont écrites sur le disque. Ceci est utile même en l'absence de tout système de files monté en lecture-écriture.

Remonter une fs en lecture seule empêche toute request d'écriture de niveau file et les appels open () avec le mode rw à partir des process, donc aucune autre modification de structure de données et fs n'est possible. La mise en memory tampon repose entre les pilotes de périphérique en mode bloc et les pilotes en mode fs, donc si le système contient des memorys tampons sales, il doit les écrire sur le support sous-jacent.

La stack typique ressemble à ceci:

  • process
  • API du file kernel io
  • pilote fs , par exemple ext3fs
  • blkdev couche d'abstraction blkdev , une API, un certain nombre de primitives utiles, des comportements par défaut, etc partie du kernel. En outre, cette couche gère les tampons et les caches de disque, ainsi que la permutation du kernel.
  • pilote de périphérique en bloc, par exemple sous-système scsi linux.
  • périphérique de stockage

Il y a aussi des loops possibles à différents niveaux. Par exemple, un file peut être utilisé comme périphérique de stockage de sauvegarde, de chiffrement de périphérique LUKS , etc.

Voici une partie du code qui effectue l'arrêt (implémentation du style System V):

 /* * Kill all processes, call /etc/init.d/halt (if present) */ void fastdown() { int do_halt = (down_level[0] == '0'); int i; #if 0 char cmd[128]; char *script; /* * Currently, the halt script is either init.d/halt OR rc.d/rc.0, * likewise for the reboot script. Test for the presence * of either. */ if (do_halt) { if (access(HALTSCRIPT1, X_OK) == 0) script = HALTSCRIPT1; else script = HALTSCRIPT2; } else { if (access(REBOOTSCRIPT1, X_OK) == 0) script = REBOOTSCRIPT1; else script = REBOOTSCRIPT2; } #endif /* First close all files. */ for(i = 0; i < 3; i++) if (!isatty(i)) { close(i); open("/dev/null", O_RDWR); } for(i = 3; i < 20; i++) close(i); close(255); /* First idle init. */ if (kill(1, SIGTSTP) < 0) { fprintf(stderr, "shutdown: can't idle init: %s.\r\n", strerror(errno)); exit(1); } /* Kill all processes. */ fprintf(stderr, "shutdown: sending all processes the TERM signal...\r\n"); kill(-1, SIGTERM); sleep(sltime ? atoi(sltime) : 3); fprintf(stderr, "shutdown: sending all processes the KILL signal.\r\n"); (void) kill(-1, SIGKILL); #if 0 /* See if we can run /etc/init.d/halt */ if (access(script, X_OK) == 0) { spawn(1, cmd, "fast", NULL); fprintf(stderr, "shutdown: %s returned - falling back " "on default routines\r\n", script); } #endif /* script failed or not present: do it ourself. */ sleep(1); /* Give init the chance to collect zombies. */ /* Record the fact that we're going down */ write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); /* This is for those who have quota installed. */ #if defined(ACCTON_OFF) # if (ACCTON_OFF > 1) && (_BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)) /* This is an alternative way to disable accounting, saving a fork() */ if (acct(NULL)) fprintf(stderr, "shutdown: can not stop process accounting: %s.\r\n", strerror(errno)); # elif (ACCTON_OFF > 0) spawn(1, "accton", "off", NULL); # else spawn(1, "accton", NULL); # endif #endif spawn(1, "quotaoff", "-a", NULL); sync(); fprintf(stderr, "shutdown: turning off swap\r\n"); spawn(0, "swapoff", "-a", NULL); fprintf(stderr, "shutdown: unmounting all file systems\r\n"); spawn(0, "umount", "-a", NULL); /* We're done, halt or reboot now. */ if (do_halt) { fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL " "or turn off power\r\n"); init_reboot(BMAGIC_HALT); exit(0); } fprintf(stderr, "Please stand by while rebooting the system.\r\n"); init_reboot(BMAGIC_REBOOT); exit(0); } 

Comme vous pouvez le voir d'abord le process kill partie est, alors nous avons:

 sync(); fprintf(stderr, "shutdown: turning off swap\r\n"); spawn(0, "swapoff", "-a", NULL); fprintf(stderr, "shutdown: unmounting all file systems\r\n"); spawn(0, "umount", "-a", NULL); 

Qui écrit datatables sur le disque en utilisant la sync . Éteint ensuite swap et démonte tous les filesystems. Puis l'arrêt ou le redémarrage réel se produit.

Description de la sync depuis la page man:

sync () provoque l'ajout de toutes les modifications en attente aux métadonnées du système de files et aux données du file mis en cache dans les filesystems sous-jacents.

Le livre pourrait être un peu vieux ou expliquant d'autres mises en œuvre de l'arrêt. Lire le code et les pages de manuel est aussi un très bon moyen d'apprendre comment fonctionne Linux.