Intereting Posts
текстовый файл с удаленным запросом, связанный с экземпляром vi Как вы находите, какие ключи являются символами «стереть» и «убить строку» в Ubuntu? Shell Script для вставки строк между файлами сделать постоянный виртуальный интерфейс? Есть ли способ настроить TCP на потерю пакетов и повторную передачу? grub не загружается при изменении порядка диска Как выполнить замену текста в иерархии больших папок? перечислите «среднюю» часть ввода в конце вывода в awk Установка Arch на VM – проблемы с DNS Как отфильтровать или извлечь файл из каталога? Может ли дескриптор файла NFS сохраняться в течение 2 полных дней без каких-либо признаков? Могу ли я использовать сценарии инициализации SysV для systemd? как заставить X указатель мыши показать выше отображаемого курсора приложения? Невозможно свернуть полноэкранную виртуальную машину В чем проблема с выходом plink?

Прояснение процедуры завершения работы

В книге «Как работает Linux» говорится, что общая процедура останова (независимо от системы init) выглядит примерно так:

  1. init запрашивает, чтобы каждый процесс закрывался чисто.
  2. Если процесс не реагирует через некоторое время, init убивает его, сначала пробуя сигнал TERM.
  3. Если сигнал TERM не работает, init использует сигнал KILL для любых отставших.
  4. Система блокирует системные файлы на месте и делает другие приготовления для выключения.
  5. Система отключает все файловые системы, отличные от корневого.
  6. Система перезагружает корневую файловую систему только для чтения .
  7. Система записывает все буферизованные данные в файловую систему с помощью программы синхронизации.
  8. Последний шаг – сообщить ядру перезагрузиться или остановить системный вызов reboot (2). Это можно сделать с помощью init или вспомогательной программы, такой как перезагрузка, останов или отключение питания.

Как синхронизировать записи своих буферов, если файловая система доступна только для чтения?

Вы правы, чтобы удивляться: этот порядок не имеет смысла. Если книга представляет ее таким образом, она небрежная и вводящая в заблуждение.

Отмонтируйте файловую систему или установите ее только для чтения, записывая все данные на диск. Когда команда umount или mount -o remount,ro возвращается mount -o remount,ro , все данные записываются на диск, и sync имеет ничего общего. Бесполезно вызывать sync раньше (данные все равно будут записываться с помощью операции umount) и бессмысленно называть ее после (ничего не будет делать).

Я думаю, что это было неверно в некоторых древних Unix-системах, где вам приходилось вызывать sync перед размонтированием. Вызвать это было еще бессмысленно.

Если вы смотрите за пределы файловых систем, могут быть случаи, когда sync делает что-то. Например, я думаю, что при sync Linux гарантирует, что метаданные массивов RAID записываются на диск. Это полезно даже при отсутствии какой-либо файловой системы, предназначенной для чтения-записи.

Перезапуск fs-чтения предотвращает любые запросы на запись на уровне файла и вызовы open () с режимом rw из процессов, поэтому дальнейшие изменения структуры данных и fs невозможны. Буферизация лежит между драйверами блоков устройств и драйверами fs, поэтому, если в системе есть грязные буферы, они должны записать их на основной носитель.

Типичный стек выглядит следующим образом:

  • обработать
  • API-интерфейс ядра io
  • fs , например ext3fs
  • blkdev абстракции blkdev , API, ряд полезных примитивов, поведение по умолчанию и т. д. часть ядра. Кроме того, этот слой управляет буферами и дисковыми кэшами, а также обеспечивает обмен файлами с ядром.
  • блок-драйвер устройства, например подсистема scsi linux.
  • накопитель

На разных уровнях возможны также петли. Например, файл может использоваться в качестве хранилища резервных LUKS устройства, шифрования устройства LUKS и т. Д.

Вот часть кода, который выполняет shutdown (реализация стиля 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); } 

Как вы видите, сначала процесс убивает часть, то у нас есть:

 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); 

Который записывает данные на диск с помощью sync . Затем отключает свопинг и удаляет все файловые системы. Затем происходит фактическая остановка или перезагрузка.

Описание sync с man-страницы:

sync () заставляет все ожидающие изменения метаданные файловой системы и данные кэшированных файлов записываться в базовые файловые системы.

Книга может быть немного старой или объяснять другую реализацию выключения. Чтение кода и man-страниц – также очень хороший способ узнать, как работает Linux.