Теперь мы рассмотрим поток 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);
493
Функция rest_init () кажется прямолинейной. Она просто создает поток, называемый init, убирает блокировку инициализации ядра и вызывает поток idle:
init/main.с
388 static void noinline rest_init(void)
389 {
CLONE_SIGHAND)
390 kernel_thread(init, NULL, CLONE_FS
3 91 unlock_kernel();
392 cpu_idle() ,-
393 }
Строка 388
Вы могли обратить внимание, что первая вызываемая start_kernel ( ) функция
не имеет приставки init. Из гл. 2 вы можете вспомнить, как мы говорили, что,
если функция имеет приставку init, это значит, что все используемые ей
Строка 490
init_idle () вызывается почти в конце start_kernel () с параметрами current и smp_processor_id () для подготовки start_kernel () для перепланировки.
kernel/sched.с
2643 void init init_idle(task_t *idle, int cpu)
2644 {
2645 runqueue_t *idle_rq = cpu_rq(cpu) , *rq = cpu_rq(task_cpu(idle));
2646 unsigned long flags; 2647
2648 local_irq_save(flags);
2649 double_rq_lock(idle_rq, rq); 2650
2 651 idle_rq->curr = idle_rq->idle = idle;
2652 deactivate_task(idle, rq) ;
2653 idle->array = NULL;
2654 idle->prio = MAX_PRIO;
2655 idle->state = TASK_RUNNING;
Строки 480-482
Как описано в гл. 2, CONFIG_* #def ine связан с переменной времени компиляции. Если во время компиляции выбрана файловая система ргос, то следующим шагом инициализации будет вызов proc_root_init ():
fs/proc/root.c
40 void init proc_root_init(void)
41 {
42 int err = proc_init_inodecache() ;
43 if (err)
44 return;
45 err = register_filesystem(&proc_fs_type);
46 if (err)
47 return;
48 proc_mnt = kern_mount(&proc_fs_type);
49 err = PTR_ERR(proc_mnt);
50 if (IS_ERR(proc_mnt)) {
51 unregister_filesystem(&proc_fs_type);
52 return;
53 }
54 proc_misc_init();
Строка 479
Функция page_writeback_init () инициализирует значение, контролируемое, когда грязные страницы записываются обратно на диск. Грязные страницы записываются на диск не сразу; они записываются по прошествии некоторого времени или после того, как некоторая часть в процентах памяти будет помечена как грязная. Эта функция init пытается определить оптимальное количество страниц, которые должны быть помечены как грязные, перед запуском фоновой и специальной записей. Фоновая запись грязных страниц занимает намного меньше процессорного времени, чем специальная запись грязных страниц:
Строка 476
Ядро Linux 2.6 использует корневое дерево для управления страницами в кеше страниц. Здесь мы просто инициализируем последовательную секцию пространства ядра для хранения корневого дерева страницы кеша:
lib/radix-tree.с
798 void init radix_tree_init(void)
799 {
800 radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
801 sizeof(struct radix_tree_node), 0,
802 SLAB_PANIC, radix_tree_node_ctor, NULL);
803 radix_tree_init_maxindex();
804 hotcpu_notifier(radix_tree_callback, 0);
lib/radix-tree.с
768 static init void radix_tree_init_maxindex(void)
769 {
Строка 475
Подсистема VFS зависит от кешей памяти, называемых SLAB-кешами, хранящими структуры, которыми эта подсистема управляет. Гл. 4 подробно описывает SLAB-кеши. Функция vf s_caches_init () инициализирует используемые системой кеши SLAB. На рис. 8.17 показан обзор иерархии вызовов из vf s_cache_init■(). Мы подробно рассмотрим каждую функцию из этой иерархии вызовов. Вы можете сверяться с этой иерархией по мере того, как мы будем рассматривать входящие в нее функции.
В табл. 8.4 подводится итог представляемых vf s_caches_in.it () или вызываемыми из нее функциями новых функций.
Строка 472
Функция buf fer_init () в f s/buf fer. с хранит данные устройства файловой системы.
fs/buffer.с
3031 void init buffer_init(void)
{
int i ;
int nrpages;
3036 bh_cachep = kmem_cache_create("buffer_head",
sizeof(struct buffer_head), 0,
0, init_buffer_head, NULL); 3039 for (i = 0; i < ARRAY_SIZE(bh_wait_queue_heads) ; i++)
init_waitqueue_head(&bh_wait_queue_heads[i].wqh); 3 044 nrpages = (nr_free_buffer_pages() * 10) / 10 0;
max_buffer_heads = nrpages * (PAGE_SIZE /
sizeof(struct buffer_head));
Строка 463
Ключевой функцией в блоке кода х86 является системная функция kmem_ceche_ create (). Эта функция создает именованный кеш. Первый параметр - это строка, используемая для ее идентификации в /proc/slabinfo.
52 9 kmem_cache_t *pgc_cache;
53 0 kmem_cache_t *pmd_cache; 531
532 void init pgtable_cache_init(void)
533 {
534 if (PTRS_PER_PMD > 1) {
53 5 pmd_cache = kmem_cache_create("pmd",
536 PTRS_PER_PMD*sizeof(pmd_t),
537 0, 538 SLAB_HWCACHE_ALIGN | SLAB_MUST_H WCACHE_ALIGN,
539 pmd_ctor,
540 NULL);
541 if (!pmd_cache)
Строка 461
Функция calibrate_delay () в init/main. с рассчитывает и выводит значения откалиброванных «BogoMips», означающих количество итераций delay (), которые может выполнить ваш процессор за один тик таймера; calibrate_delay () позволяет примерно уравнять задержки на процессорах с разной скоростью. Результирующее значение — это в основном индикатор скорости работы процессора, который хранится в loop_pre_j if fу, а функции udelay () и mdelay () используются для установки количества выполняемых итераций delay ():
Init/main.с
void init calibrate_delay(void)
{