Поток init (или процесс 1 )

Теперь мы рассмотрим поток init. Обратите внимание, что мы пропускаем все связанные с SMP функции.

init/main.с
601 static int init(void * unused)
602 {
603 lock_kernel();
612 child_reaper = current;
if (sys_access((const char user *) "/init", 0) == 0)
execute_command = "/init"; else
prepare_namespace();
free_initmem();
unlock_kernel();
system_state = SYSTEM_RUNNING;
if (sys_open((const char user *) "/dev/console", 0_RDWR, 0) < 0)
printk("Warning: unable to open an initial console.\n");
(void) sys_dup(0); (void) sys_dup(0);
if (execute_command) run_init_process(execute_command);
run_init_process("/sbin/init"); run_init_process("/etc/init"); run_init_process("/bin/init"); run_init_process("/bin/sh"),-
panic("No init found. Try passing init= option to kernel.");
Строка 612
Поток in.it настроен на уничтожение любых потоков, чьи родители мертвы. Переменная сп11с_геарег является глобальным указателем на task_struct и определена в 1п^/та1п.с. Эта переменная входит в игру в «повторяющейся функции» и используется для ссылки на поток, который должен стать новым родителем. Мы ссылаемся на функции герагеп^^_1п^ () (кегпе1/ех^. с), choose_new_parent () (кегпе1/ех^. с) и £огде^ог1д1па1_рагег^ () (кегпе1/ех^. с), так как они используют сЬ11с1_геарег для сброса вызова родителя потока.
Строка 629
Функция с!о_Ьаз1с_зе^р () инициализирует модель драйвера, интерфейс эу-эс^!, интерфейс сетевых сокетов и поддержку рабочей очереди.
Строка 553
Функция driver_init() (drivers/base/init.c) инициализирует все подсистемы, связанные с поддержкой драйверов. Это первая часть инициализации драйверов. Вторая появляется в строке 563 с вызовом do_initcalls ().
Строки 555-557
Интерфейс sysctl предоставляет поддержку динамического изменения параметров ядра. Это означает, что параметры ядра, поддерживающие sysctl, могут быть изменены во время работы без необходимости перекомпиляции и перезагрузки ядра; sysctl_init () (kernel/sysctl. с) инициализирует интерфейс sysctl. Более подробную информацию о sysctl читайте в соответствующих мэн-страницах (man sysctl).
Строка 560
Функция sock_init() представляет собой пустышку с простым printk, если ядро сконфигурировано без поддержки сети. В этом случае sock_init () определяется в net/nonet. с. В случае поддержки сети, когда sock_init () определена в net/socket.с, она инициализирует кеш памяти для использования поддержки сети и регистрации файловой системы, поддерживающей сеть.
Строка 562
Вызов init_workqueue настраивается для работы очереди цепи уведомлений. Гл. 10, «Добавление вашего кода в ядро», обсуждает рабочую очередь.
Строка 563
Функция do_initcalls () (init/main.с) составляет вторую часть инициализации драйвера устройства. Эта функция последовательно вызывает элементы массива указателей на функции, соответствующие функциям инициализации встроенных устройств1.
Строки 635-638
Если раннее пользовательское пространство функции in.it существует, ядро не подготавливает пространство имен; оно позволяет выполнение этой функции. В противном случае выполняется вызов ргераге_патезрасе (). Пространство имен связано с точкой монтирования иерархии файловой системы
init/do_mounts.c
383 void init prepare_namespace(void)
384 {
3 85 int is_floppy;
386
3 87 mount_devfs() ;
391 if (saved_root_name[0]) {
3 92 root_device_name = saved_root_name;
3 93 ROOT_DEV = name_to_dev_t(root_device_name);
394 if (strncmp(root_device_name, "/dev/", 5) == 0)
395 root_device_name += 5;
396 }
397
3 98 is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
399
400 if (initrd_load())
401 goto out;
402
403 if (is_floppy && rd_doload && rd_load_disk(0))
404 ROOT_DEV = Root_RAM0;
405
40 6 mount_root();
407 out:
408 umount_devfs("/dev");
409 sys_mount(".", "/", NULL, MS_MOVE, NULL);
410 sys_chroot(".") ;
411 security_sb_post_mountroot() ;
412 mount_devfs_fs () ;
413 }

Строка 387
Функция mount_devf s () создает структуры, связанные с монтированием /dev. Нам нужно смонтировать /dev, так как мы используем ее для ссылок на имя корневого устройства.

Обратитесь по адресу http://geek.vtnet.ca/doc/initcall/ за подробным объяснение работы initcall от Тревора Военера (Trevor Woerner).
Строки 391-396
Этот блок кода устанавливает глобальную переменную КООТ_БЕУ для инициализации корневого устройства, передаваемого через параметры загрузки ядра.
Строка 398
Простое сравнение старшего числа, означающего, что корневым устройством является флоппи-диск.
Строки 400-401
Вызов 1П^гс_1оас! () монтирует диск в памяти, если диск в памяти нужно обозначить как корень файловой системы ядра. В этом случае она возвращает 1 и выполняет переход к нашей метке, которая отменяет все выполненные приготовления для устройства корневой файловой системы.
Строка 406
Вызов тоипЬ_гооЪ выполняет основную часть монтирования корневой файловой системы. Давайте рассмотрим эту функцию поближе.
init/do_mounts.c
353 void init mount_root(void)
354 {
355 #ifdef CONFIG_ROOT_NFS
356 if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
3 57 if (mount_nfs_root())
358 return;
359
360 printk(KERN_ERR "VFS: Unable to mount root fs via NFS,
trying floppy.\n");
3 61 ROOT_DEV = Root_FD0;
362 }
363 #endif
3 64 #ifdef CONFIG_BLK_DEV_FD
3 65 if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
367 if (rd_doload==2) {
368 if (rd_load_disk(l)) {
3 69 ROOT_DEV = Root_RAMl;
370 root_device_name = NULL;
371 }
372 } else
373 change_floppy("root floppy");
374 }
375 #endif
376 create_dev("/dev/root", ROOT_DEV, root_device_name);
Строки 355-358
Если ядро сконфигурировано для монтирования файловой системы NFS, мы выполняем mount_nf s_root (). Если монтирование NFS не удалось, ядро выводит соответствующее сообщение и далее пытается смонтировать в качестве корневой файловой системы флоппи-диск.
Строки 364-375
В этом блоке кода ядро пытается смонтировать корневой флоппи-диск1. Строка 377
Эта функция выполняет основную часть монтирования корневого устройства. Теперь мы возвращаемся в init ().
Строка 645
Вызов free_initmem() освобождает все сегменты памяти, используемые функ-
циями с приставкой init. Она отмечает наш выход из чистого пространства
ядра и начало настройки пользовательских данных.
Строки 649-650
Открытие консоли инициализации.
Строки 662-668
Переменная execute_command, настраиваемая в init_setup (), хранит значение параметров загрузки, содержащих имя программы init, вызываемой, если мы не хотим вызывать /sbin/init по умолчанию. Если имя программы init принято, она получает приоритет обычной /sbin/init. Обратите внимание, что вызов run_init_process () (init/main. с) не возвращается, так как он заканчивается вызовом execve (). Поэтому первый вызов функции init используется только для первого удачного запуска. В случае, если программа init не найдена, мы можем использовать оболочку bash для ее запуска.
Строка 670
Это выражение паники достигается, только если все наши попытки выполнения различных программ init провалились.
Она завершает инициализацию ядра. Отсюда процесс init связывается с инициализацией системы и запускает все необходимые для регистрации и поддержки работы с пользователями процессы и демоны