張超《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 我的代碼可見https://www.shiyanlou.com/courses/reports/986221 在這裡我們用的是linux-3.18.6版本,以下簡寫
張超《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000
我的代碼可見https://www.shiyanlou.com/courses/reports/986221
在這裡我們用的是linux-3.18.6版本,以下簡寫成linux。
start_kernel在 /linux/init/main.c中定義:
這個函數是內核由引導程式引導以後,由自解壓程式解壓以後執行的第一個函數,可以認為是整個內核的入口函數,以後我分析的代碼全部從這個函數開始!
這個函數做的事情相對比較簡單,就是線性的初始化一些內核的基礎機制,如中斷,記憶體管理,進程管理,信號,文件系統,KO等!最後就啟動一個init線程,init線程再讀取文件系統里的init程式,做為系統的第一個進程而存在!
其實,start_kernel函數是0是做為0號進程存在的,它在最後就是空轉CPU:
500asmlinkage __visible void __init start_kernel(void) 501{ 502 char *command_line; 503 char *after_dashes; 504 505 /* 506 * Need to run as early as possible, to initialize the 507 * lockdep hash: 508 */ 509 lockdep_init(); 510 set_task_stack_end_magic(&init_task); 511 smp_setup_processor_id(); 512 debug_objects_early_init(); 513 514 /* 515 * Set up the the initial canary ASAP: 516 */ 517 boot_init_stack_canary(); 518 519 cgroup_init_early(); 520 521 local_irq_disable(); 522 early_boot_irqs_disabled = true; 523 524/* 525 * Interrupts are still disabled. Do necessary setups, then 526 * enable them 527 */ 528 boot_cpu_init(); 529 page_address_init(); 530 pr_notice("%s", linux_banner); 531 setup_arch(&command_line); 532 mm_init_cpumask(&init_mm); 533 setup_command_line(command_line); 534 setup_nr_cpu_ids(); 535 setup_per_cpu_areas(); 536 smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ 537 538 build_all_zonelists(NULL, NULL); 539 page_alloc_init(); 540 541 pr_notice("Kernel command line: %s\n", boot_command_line); 542 parse_early_param(); 543 after_dashes = parse_args("Booting kernel", 544 static_command_line, __start___param, 545 __stop___param - __start___param, 546 -1, -1, &unknown_bootoption); 547 if (!IS_ERR_OR_NULL(after_dashes)) 548 parse_args("Setting init args", after_dashes, NULL, 0, -1, -1, 549 set_init_arg); 550 551 jump_label_init(); 552 553 /* 554 * These use large bootmem allocations and must precede 555 * kmem_cache_init() 556 */ 557 setup_log_buf(0); 558 pidhash_init(); 559 vfs_caches_init_early(); 560 sort_main_extable(); 561 trap_init(); 562 mm_init(); 563 564 /* 565 * Set up the scheduler prior starting any interrupts (such as the 566 * timer interrupt). Full topology setup happens at smp_init() 567 * time - but meanwhile we still have a functioning scheduler. 568 */ 569 sched_init(); 570 /* 571 * Disable preemption - early bootup scheduling is extremely 572 * fragile until we cpu_idle() for the first time. 573 */ 574 preempt_disable(); 575 if (WARN(!irqs_disabled(), 576 "Interrupts were enabled *very* early, fixing it\n")) 577 local_irq_disable(); 578 idr_init_cache(); 579 rcu_init(); 580 context_tracking_init(); 581 radix_tree_init(); 582 /* init some links before init_ISA_irqs() */ 583 early_irq_init(); 584 init_IRQ(); 585 tick_init(); 586 rcu_init_nohz(); 587 init_timers(); 588 hrtimers_init(); 589 softirq_init(); 590 timekeeping_init(); 591 time_init(); 592 sched_clock_postinit(); 593 perf_event_init(); 594 profile_init(); 595 call_function_init(); 596 WARN(!irqs_disabled(), "Interrupts were enabled early\n"); 597 early_boot_irqs_disabled = false; 598 local_irq_enable(); 599 600 kmem_cache_init_late(); 601 602 /* 603 * HACK ALERT! This is early. We're enabling the console before 604 * we've done PCI setups etc, and console_init() must be aware of 605 * this. But we do want output early, in case something goes wrong. 606 */ 607 console_init(); 608 if (panic_later) 609 panic("Too many boot %s vars at `%s'", panic_later, 610 panic_param); 611 612 lockdep_info(); 613 614 /* 615 * Need to run this when irqs are enabled, because it wants 616 * to self-test [hard/soft]-irqs on/off lock inversion bugs 617 * too: 618 */ 619 locking_selftest(); 620 621#ifdef CONFIG_BLK_DEV_INITRD 622 if (initrd_start && !initrd_below_start_ok && 623 page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) { 624 pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n", 625 page_to_pfn(virt_to_page((void *)initrd_start)), 626 min_low_pfn); 627 initrd_start = 0; 628 } 629#endif 630 page_cgroup_init(); 631 debug_objects_mem_init(); 632 kmemleak_init(); 633 setup_per_cpu_pageset(); 634 numa_policy_init(); 635 if (late_time_init) 636 late_time_init(); 637 sched_clock_init(); 638 calibrate_delay(); 639 pidmap_init(); 640 anon_vma_init(); 641 acpi_early_init(); 642#ifdef CONFIG_X86 643 if (efi_enabled(EFI_RUNTIME_SERVICES)) 644 efi_enter_virtual_mode(); 645#endif 646#ifdef CONFIG_X86_ESPFIX64 647 /* Should be run before the first non-init thread is created */ 648 init_espfix_bsp(); 649#endif 650 thread_info_cache_init(); 651 cred_init(); 652 fork_init(totalram_pages); 653 proc_caches_init(); 654 buffer_init(); 655 key_init(); 656 security_init(); 657 dbg_late_init(); 658 vfs_caches_init(totalram_pages); 659 signals_init(); 660 /* rootfs populating might need page-writeback */ 661 page_writeback_init(); 662 proc_root_init(); 663 cgroup_init(); 664 cpuset_init(); 665 taskstats_init_early(); 666 delayacct_init(); 667 668 check_bugs(); 669 670 sfi_init_late(); 671 672 if (efi_enabled(EFI_RUNTIME_SERVICES)) { 673 efi_late_init(); 674 efi_free_boot_services(); 675 } 676 677 ftrace_init(); 678 679 /* Do the rest non-__init'ed, we're now alive */ 680 rest_init(); 681}start_kernel代碼
我們的實驗截圖在最後面;
我們規定【】顯示的是所在的文件目錄以及行數,預設是在/init/main.c中,都是在linux里;前面是在init/main.c的行號,後面是函數自己定義所在的目錄及行數。
【502】 char * command_line;
/*命令行,用來存放bootloader傳遞過來的參數*/
【509】 lockdep_init(); 【kernel/locking/lockdep.c 3975】
/*建立一個哈希表(hash tables),就是一個前後指向的指針結構體數組。 (函數的主要作用是初始化鎖的狀態跟蹤模塊。由於內核大量使用鎖來進行多進程多處理器的同步操作,死鎖就會在代碼不合理的時候出現,但是要定位哪個鎖比較困難,用哈希表可以跟蹤鎖的使用狀態。死鎖情況:一個進程遞歸加鎖同一把鎖;同一把鎖在兩次中斷中加鎖;幾把鎖形成閉環死鎖)*/
【510】set_task_stack_end_magic(&init_task); 【kernel/fork.c 297】
/*init_task即手工創建的PCB,0號進程即最終的idle進程*/
【511】 smp_setup_processor_id(); 【473】
/*針對SMP處理器,用於獲取當前CPU的硬體ID,如果不是多核,函數為空 (判斷是否定義了CONFIG_SMP,如果定義了調用read_cpuid_mpidr讀取寄存器CPUID_MPIDR的值,就是當前正在執行初始化的CPU ID,為了在初始化時做個區分,初始化完成後,所有處理器都是平等的,沒有主從)*/
【512】debug_objects_early_init();【lib/debugobjects.c 1007】
/*初始化哈希桶(hash buckets)並將static object和pool object放入poll列表,這樣堆棧就可以完全操作了 (這個函數的主要作用就是對調試對象進行早期的初始化,就是HASH鎖和靜態對象池進行初始化,執行完後,object tracker已經開始完全運作了)*/
【517】boot_init_stack_canary();【arch/x86/include/asm/stackprotector.h 58】
/*初始化堆棧保護的值,防止棧溢出*/
【519】cgroup_init_early();【kernel/cgroup.c 4882】
/*在系統啟動時初始化cgroups,同時初始化需要early_init的子系統 (這個函數作用是控制組(control groups)早期的初始化,控制組就是定義一組進程具有相同資源的占有程度,比如,可以指定一組進程使用CPU為30%,磁碟IO為40%,網路帶寬為50%。目的就是為了把所有進程分配不同的資源)*/
【521】local_irq_disable();【】
/*關閉當前CPU的所有中斷響應,操作CPSR寄存器。對應後面的*/
【522】early_boot_irqs_disabled = true;
/*系統中斷關閉標誌,當early_init完畢後,會恢復中斷設置標誌為false。*/
【528】boot_cpu_init();【463】
/*設置當前引導系統的CPU在物理上存在,在邏輯上可以使用,並且初始化準備好,即激活當前CPU (在多CPU的系統里,內核需要管理多個CPU,那麼就需要知道系統有多少個CPU,在內核里使用cpu_present_map點陣圖表達有多少個CPU,每一位表示一個CPU的存在。如果是單個CPU,就是第0位設置為1。雖然系統里有多個CPU存在,但是每個CPU不一定可以使用,或者沒有初始化,在內核使用cpu_online_map點陣圖來表示那些CPU可以運行內核代碼和接受中斷處理。隨著移動系統的節能需求,需要對CPU進行節能處理,比如有多個CPU運行時可以提高性能,但花費太多電能,導致電池不耐用,需要減少運行的CPU個數,或者只需要一個CPU運行。這樣內核又引入了一個cpu_possible_map點陣圖,表示最多可以使用多少個CPU。在本函數里就是依次設置這三個點陣圖的標誌,讓引導的CPU物理上存在,已經初始化好,最少需要運行的CPU。)*/
【529】page_address_init();【mm/highmem.c 478】
/*初始化高端記憶體的映射表 (在這裡引入了高端記憶體的概念,那麼什麼叫做高端記憶體呢?為什麼要使用高端記憶體呢?其實高端記憶體是相對於低端記憶體而存在的,那麼先要理解一下低端記憶體了。在32位的系統里,最多能訪問的總記憶體是4G,其中3G空間給應用程式,而內核只占用1G的空間。因此,內核能映射的記憶體空間,只有1G大小,但實際上比這個還要小一些,大概是896M,另外128M空間是用來映射高端記憶體使用的。因此0到896M的記憶體空間,就叫做低端記憶體,而高於896M的記憶體,就叫高端記憶體了。如果系統是64位系統,當然就沒未必要有高端記憶體存在了,因為64位有足夠多的地址空間給內核使用,訪問的記憶體可以達到10G都沒有問題。在32位系統里,內核為了訪問超過1G的物理記憶體空間,需要使用高端記憶體映射表。比如當內核需要讀取1G的緩存數據時,就需要分配高端記憶體來使用,這樣才可以管理起來。使用高端記憶體之後,32位的系統也可以訪問達到64G記憶體。在移動操作系統里,目前還沒有這個必要,最多才1G多記憶體)*/
【530】pr_notice("%s", linux_banner);【include/linux/printk.h 244】
/*輸出各種信息(Linux_banner是在kernel/init/version.c中定義的,這個字元串是編譯腳本自動生成的)*/
【530】setup_arch(&command_line);【arch/x86/kernel/setup.c 857】
/*很重要的一個函數arch/arm/kernel/setup.c
(內核架構相關初始化函數,是非常重要的一個初始化步驟。其中包含了處理器相關參數的初始化、內核啟動參數(tagged list)的獲取和前期處理、記憶體子系統的早期初始化(bootmem分配器))*/
【532】mm_init_cpumask(&init_mm);【/include/linux/mm_types.h 459】
/*每一個任務都有一個mm_struct結構來管理記憶體空間,init_mm是內核的mm_struct*/
【533】setup_command_line(command_line);【371】
/*對cmdline進行備份和保存*/
【534】setup_nr_cpu_ids();【kernel/smp.c 538】
/*設置最多有多少個nr_cpu_ids結構*/
【535】setup_per_cpu_areas();【arch/x86/kernel/setup_percpu.c 167】
/*為系統中每個CPU的per_cpu變數申請空間,同時拷貝初始化段里數據(.data.percpu)*/
【536】smp_prepare_boot_cpu();【arch/x86/include/asm/smp.h 102】
/*為SMP系統里引導CPU(boot-cpu)進行準備工作。在ARM系統單核里是空函數*/
【538】build_all_zonelists(NULL, NULL);【mm/page_alloc.c 3865】
/*設置記憶體管理相關的node(節點,每個CPU一個記憶體節點)和其中的zone(記憶體域,包含於節點中,如)數據結構,以完成記憶體管理子系統的初始化,並設置bootmem分配器*/
【539】page_alloc_init();【mm/page_alloc.c 5567】
/*設置記憶體頁分配通知器*/
【541】pr_notice("Kernel command line: %s\n", boot_command_line);【】見前面
【542】parse_early_param();【445】
/*解析cmdline中的啟動參數*/
【543】after_dashes = parse_args("Booting kernel",static_command_line, __start___param,__stop___param - __start___param,-1, -1, &unknown_bootoption);【kernel/params.c 191】
/*這行代碼主要對傳入內核參數進行解釋,如果不能識別的命令就調用最後參數的函數*/
【551】jump_label_init();【include/linux/jump_label.h 146】
【557】setup_log_buf(0);【kernel/printk/printk.c 887】
/*使用bootmeme分配一個記錄啟動信息的緩衝區*/
【558】pidhash_init();【kernel/pid.c 572】
/*進程ID的HASH表初始化,用bootmem分配並初始化PID散列表,由PID分配器管理空閑和已指派的PID,這樣可以提供通PID進行高效訪問進程結構的信息。LINUX里共有四種類型的PID,因此就有四種HASH表相對應。*/
【559】vfs_caches_init_early();【fs/dcache.c 3410】
/*前期虛擬文件系統(vfs)的緩存初始化*/
【560】sort_main_extable();【kernel/extable.c 42】
/*對內核異常表(exception table)按照異常向量號大小進行排序,以便加速訪問*/
【561】trap_init();【arch/x86/kernel/traps.c 792】
/*對內核陷阱異常進行初始化,在ARM系統里是空函數,沒有任何的初始化*/
【562】mm_init();【486】
/*標記哪些記憶體可以使用,並且告訴系統有多少記憶體可以使用,當然是除了內核使用的記憶體以外
(初始化內核記憶體分配器,包括六個子函數
1、page_cgroup_init_flatmem();獲取page_cgroup所需記憶體
2、mem_init;關閉並釋放bootmem分配器,列印記憶體信息,內核啟動時看到Virtual kernel memory layout:的信息就是這個函數的
3、kmem_cache_init();初始化slab分配器
4、percpu_init_late();PerCPU變數系統後期初始化
5、pgtable_cache_init();也表緩存初始化,arm中是個空函數 6、vmalloc_init();初始化虛擬記憶體分配器*/
【569】sched_init();【kernel/sched/core.c 6998】
/*對進程調度器的數據結構進行初始化,創建運行隊列,設置當前任務的空線程,當前任務的調度策略為CFS調度器 */
【574】preempt_disable();【】
/*關閉優先順序調度。由於每個進程任務都有優先順序,目前系統還沒有完全初始化,還不能打開優先順序調度。*/
【575】if (WARN(!irqs_disabled(),"Interrupts were enabled *very* early, fixing it\n")) {local_irq_disable();}【】
/*這段代碼主要判斷是否過早打開中斷,如果是這樣,就會提示,並把中斷關閉*/
【578】idr_init_cache();【lib/idr.c 826】
/*為IDR機制分配緩存,主要是為 structidr_layer結構體分配空間*/
【579】rcu_init();【kernel/rcu/tree.c 3749】
/*初始化直接讀拷貝更新的鎖機制。 Read-Copy Update (RCU主要提供在讀取數據機會比較多,但更新比較的少的場合,這樣減少讀取數據鎖的性能低下的問題。)*/
【580】context_tracking_init();【kernel/context_tracking.c 169】
【581】radix_tree_init();【lib/radix-tree.c 1480】
/*內核radis 樹演算法初始化*/
【583】early_irq_init();【kernel/irq/irqdesc.c 230】
/*前期外部中斷描述符初始化,主要初始化數據結構*/
【584】init_IRQ();【arch/x86/kernel/irqinit.c 84】
/*對應架構特定的中斷初始化函數,在ARM中就是machine_desc->init_irq(),就是運行設備描述結構體中的init_irq函數[arch/arm/mach-msm/board-xxx.c]*/
【585】tick_init();【kernel/time/tick-common.c 400】
/*初始化內核時鐘系統,tick control,調用clockevents_register_notifier,就是監聽時鐘變化事件 (這個函數主要作用是初始化時鐘事件管理器的回調函數,比如當時鐘設備添加時處理。在內核里定義了時鐘事件管理器,主要用來管理所有需要周期性地執行任務的設備)*/
【586】rcu_init_nohz();【】
【587】init_timers();【kernel/time/timer.c 1671】
/*初始化引導CPU的時鐘相關的數據結構,註冊時鐘的回調函數,當時鐘到達時可以回調時鐘處理函數,最後初始化時鐘軟體中斷處理*/
【588】hrtimers_init();【kernel/time/hrtimer.c 1742】
/*初始化高精度的定時器,並設置回調函數。*/
【589】softirq_init();【/kernel/softirq.c 630】
/*初始化軟體中斷,軟體中斷與硬體中斷區別就是中斷發生時,軟體中斷是使用線程來監視中斷信號,而硬體中斷是使用CPU硬體來監視中斷。*/
【590】timekeeping_init();【kernel/time/timekeeping.c 993】
/*初始化系統時鐘計時,並且初始化內核里與時鐘計時相關的變數。*/
【591】time_init();【arch/x86/kernel/time.c 94】
/*初始化系統時鐘。開啟一個硬體定時器,開始產生系統時鐘就是system_timer的初始化,arch/arm/mach-msm/board-*.c */
【592】sched_clock_postinit();【kernel/time/sched_clock.c 172】
【593】perf_event_init();【kernel/events/core.c 8208】
/*CPU性能監視機制初始化,此機制包括CPU同一時間執行指令數,cache miss數,分支預測失敗次數等性能參數*/
【594】profile_init();【/kernel/profile.c 99】
/*分配內核性能統計保存的記憶體,以便統計的性能變數可以保存到這裡*/
【595】call_function_init();【kernel/smp.c 89】
/*初始化所有CPU的call_single_queue,同時註冊CPU熱插拔通知函數到CPU通知鏈中*/
【596】WARN(!irqs_disabled(), "Interrupts were enabled early\n"); early_boot_irqs_disabled = false; local_irq_enable();【】
/*對應前面的local_irq_disable() (打開本CPU的中斷,也即允許本CPU處理中斷事件,在這裡打開引CPU的中斷處理。如果有多核心,別的CPU還沒有打開中斷處理。)*/
【600】kmem_cache_init_late();【/mm/slub.c 3612】
/*這是內核記憶體緩存(slab分配器)的後期初始化,當初始化完成之後,就可以使用通用記憶體緩存了*/
【607】console_init();【drivers/tty/tty_io.c 3510】
/*初始化控制台,從這個函數之後就可以輸出內容到控制台了。在這個函數初化之前,都沒有辦法輸出內容,就是輸出,也是寫到輸出緩衝區里,緩存起來,等到這個函數調用之後,就立即輸出內容*/
【608】if (panic_later) panic("Too many boot %s vars at `%s'", panic_later,panic_param);【】
/*判斷分析輸入的參數是否出錯,如果有出錯,就啟動控制台輸出之後,立即列印出錯的參數,以便用戶立即看到出錯的地方。*/
【612】lockdep_info();【kernel/locking/lockdep.c 3997】
/*列印鎖的依賴信息,用來調試鎖。通過這個函數可以查看目前鎖的狀態,以便可以發現那些鎖產生死鎖,那些鎖使用有問題。*/
【619】locking_selftest();【lib/locking-selftest.c 1795】
/*測試鎖的API是否使用正常,進行自我測試。比如測試自旋鎖、讀寫鎖、一般信號量和讀寫信號量。*/
【621】
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
page_to_pfn(virt_to_page((void *)initrd_start)),
min_low_pfn);
initrd_start = 0;
}
#endif【】
/*檢查initrd的位置是否符合要求,也就是判斷傳遞進來initrd_start對應的物理地址是否正常,如果有誤就列印錯誤信息,並清零initrd_start。*/
【630】page_cgroup_init();【mm/page_cgroup.c 271】
/*初始化容器組的頁面記憶體分配,mem_cgroup是cgroup體系中提供的用於memory隔離的功能,*/
【631】debug_objects_mem_init();【lib/debugobjects.c 1081】
/*這個函數是創建調試對象記憶體分配初始化,所以緊跟記憶體緩存初始化後面*/
【632】kmemleak_init();【mm/kmemleak.c 1807】
/*內核記憶體泄漏檢測機制初始化;*/
【633】setup_per_cpu_pageset();【mm/page_alloc.c 4309】
/*創建每個CPU的高速緩存集合數組並初始化,此前只有啟動頁組。因為每個CPU都不定時需要使用一些頁面記憶體和釋放頁面記憶體,為了提高效率,就預先創建一些記憶體頁面作為每個CPU的頁面集合。*/
【634】numa_policy_init();【mm/mempolicy.c 2587】
/*初始化NUMA的記憶體訪問策略。所謂NUMA,它是NonUniform Memory AccessAchitecture(非一致性記憶體訪問)的縮寫,主要用來提高多個CPU訪問記憶體的速度。因為多個CPU訪問同一個節點的記憶體速度遠遠比訪問多個節點的速度來得快。*/
【635】if (late_time_init) late_time_init();【121】
/*主要運行時鐘相關後期的初始化功能。*/
【637】sched_clock_init();【kernel/sched/clock.c 145】
/*對每個CPU進行系統進程調度時鐘初始化*/
【638】calibrate_delay();【init/calibrate.c 274】
/*主要計算CPU需要校準的時間,這裡說的時間是CPU執行時間。如果是引導CPU,這個函數計算出來的校準時間是不需要使用的,主要使用在非引導CPU上,因為非引導CPU執行的頻率不一樣,導致時間計算不准確。BogoMIPS值,也是衡量cpu性能的標誌*/
【639】pidmap_init();【/kernel/pid.c 586】
/*進程點陣圖初始化,一般情況下使用一頁來表示所有進程占用情況。*/
【640】anon_vma_init();【mm/rmap.c 376】
/*初始化反向映射的匿名記憶體,提供反向查找記憶體的結構指針位置,快速地回收記憶體。*/
【641】acpi_early_init();【/drivers/acpi/bus.c 470】
/*這個函數是初始化ACPI電源管理。高級配置及電源介面(Advanced Configuration and Power Interface)ACPI規範介紹ACPI能使軟、硬體、操作系統(OS),主機板和外圍設備,依照一定的方式管理用電情況,系統硬體產生的Hot-Plug事件,讓操作系統從用戶的角度上直接支配即插即用設備,不同於以往直接通過基於BIOS 的方式的管理。*/
【642】
#ifdef CONFIG_X86
if (efi_enabled(EFI_RUNTIME_SERVICES))
efi_enter_virtual_mode();
#endif【】
/*初始化EFI的介面,併進入虛擬模式。EFI是ExtensibleFirmware Interface的縮寫,就是INTEL公司新開發的BIOS介面。*/
【650】thread_info_cache_init();【478】
/*線程信息(thread_info)的緩存初始化。*/
【651】cred_init();【/kernel/cred.c 561】
/*任務信用系統初始化 */
【652】fork_init(totaltam_pages)【kernel/fork.c 652】
/*根據當前物理記憶體計算出來可以創建進程(線程)的最大數量,併進行進程環境初始化,為task_struct分配空間。*/
【653】proc_caches_init();【kernel/fork.c 1762】
/*進程緩存初始化,為進程初始化創建機制所需的其他數據結構申請空間*/
【654】buffer_init();【fs/buffer.c 3413】
/*初始化文件系統的緩衝區,並計算最大可以使用的文件緩存。*/
【655】key_init();【security/keys/key.c 1123】
/*初始化內核安全鍵管理列表和結構,內核密鑰管理系統*/
【656】security_init();【security/security.c 65】
/*初始化內核安全管理框架,以便提供訪問文件/登錄等許可權。*/
【657】dbg_late_init();【kernel/debug/debug_core.c 839】
/*內核調試系統後期初始化 */
【658】vfs_caches_init(totalram_pages);【/fs/dcache.c 3416】
/*虛擬文件系統進行緩存初始化,提高虛擬文件系統的訪問速度*/
【659】signals_init();【kernel/signal.c 3623】
/*初始化信號隊列緩存。信號管理系統*/
【661】page_writeback_init();【mm/page-writeback.c 1765】
/*頁面寫機制初始化 */
【662】proc_root_init();【fs/proc/root.c 165】
/*初始化系統進程文件系統,主要提供內核與用戶進行交互的平臺,方便用戶實時查看進程的信息。*/
【663】cgroup_init();【kernel/cgroup.c 4916】
/*進程式控制制組正式初始化,主要用來為進程和其子程提供性能控制。比如限定這組進程的CPU使用率為20% */
【664】cpuset_init();【/kernel/cpuset.c 2068】
/*初始化CPUSET,CPUSET主要為控制組提供CPU和記憶體節點的管理的結構。*/
【665】taskstats_init_early();【kernel/taskstats.c 691】
/*任務狀態早期初始化,為結構體獲取高速緩存,並初始化互斥機制。任務狀態主要向用戶提供任務的狀態信息。*/
【666】delayacct_init();【kernel/delayacct.c 35】
/*任務延遲機制初始化,初始化每個任務延時計數。當一個任務等CPU運行,或者等IO同步時,都需要計算等待時間。*/
【668】check_bugs();【arch/x86/kernel/cpu/bugs.c 66】
/*檢查CPU配置、FPU等是否非法使用不具備的功能,檢查CPU BUG,軟體規避BUG*/
【670】sfi_init_late();【drivers/sfi/sfi_core.c 500】
/*SFI 初始程式晚期設置函數*/
【677】ftrace_init();【kernel/trace/ftrace.c 4697】
/*功能跟蹤調試機制初始化,初始化內核跟蹤模塊,ftrace的作用是幫助開發人員瞭解Linux 內核的運行時行為,以便進行故障調試或性能分析 function trace.*/
【680】rest_init();【393】
/*剩餘的初始化,至此,內核已經開始工作了*/