通用寄存器的作用 Linux啟動(dòng)過程描述 第一步:使用Boot Loader(一般是U-boot)加載Linux內(nèi)核映像到內(nèi)存,并負(fù)責(zé)目標(biāo)系統(tǒng)的基本初始化過程,,并搜集這個(gè)系統(tǒng)的基本信息,,比如內(nèi)存大小、處理器主頻,、外設(shè)的使用情況等一系列信息。然后把這些信息傳遞給linux內(nèi)核,。然后Boot loader把linux內(nèi)核復(fù)制到從0x0000 0000 開始的物理內(nèi)存處(虛擬地址一般為0xc000 0000處)開始執(zhí)行,。 備注:這一部分內(nèi)容,,本文不做重點(diǎn)介紹。請參考《uboot啟動(dòng)過程學(xué)習(xí)總結(jié).doc》
*
******************************************************************************* 記錄2:linux kernel 鏈接文件,、入口函數(shù)和相關(guān)宏定義等 Bootstraploader過程:從文件\arch\powerpc\boot\zImage.lds中可以看出,,bootstraploader的入口為_zimage_start。在代碼arch\powerpc\boot\crt0.S中 D:\virtual_machine\share_folder\linux-2.6.23\arch\powerpc\boot\zImage.lds中定義的入口地址為4MB,,見下面 SECTIONS { . = (4*1024*1024); _start = .; .text : 進(jìn)入linux內(nèi)核:從vmlinux.lds看到,,內(nèi)核入口為_stext,通過段.text.head 將代碼定位到0xc0000000處,。 在代碼arch/powerpc/kernel/head_32.S中_stext之后緊接著是_start,,他們之間沒有代碼,他們表示相同的地址,。 在vmlinux.lds中將.text.head規(guī)劃為.text的第一個(gè)字段(保證了地址定位到0xc0000000),。 *******************************************************************************
第二步:Linux系統(tǒng)的初始化 1、 bootstraploader 過程 注意:需要知道從uboot跳到此處時(shí),,r3寄存器的內(nèi)容,,以及其他register的內(nèi)容 如果運(yùn)行地址和鏈接地址不同,則修正got表中各個(gè)函數(shù)的指針 清零BSS段 調(diào)用platform_init(),,保存bd到__res,,初始化ppc_md(ppc module)中的各個(gè)函數(shù)。 調(diào)用arch\powerpc\boot\main.c中的start() 在start()中: 1.1將命令行拷貝到cmdline中 1.2調(diào)用open函數(shù)打開串口 1.3解壓縮kernel代碼 1.4解壓縮ramdisk image 1.5最終初始化設(shè)備樹 1.6跳到內(nèi)核代碼中執(zhí)行 有兩個(gè)調(diào)用語句,,應(yīng)該是運(yùn)行了語句:kentry(ft_addr, 0, NULL); need confirm 2,、 進(jìn)入linux內(nèi)核 入口:arch/powerpc/kernel/head_32.S中的_start。 2.1 early_init() ,,arch/powerpc/kernel/setup_32.c中 計(jì)算運(yùn)行地址和鏈接地址的差值,。根據(jù)cpu型號(hào)調(diào)用do_feature_fixups函數(shù)來對(duì)__ftr_fixup段進(jìn)行修復(fù)處理。 例如若HIDO寄存器的HIGH_BAT_EN位置位,,另外的4組寄存器 IBATs (4–7) 和 4組 DBATs (4-7) 將會(huì)被激活,,__ftr_fixup段中對(duì)這8組寄存器進(jìn)行初始化的代碼就會(huì)生效;否則__ftr_fixup中的這段代碼就會(huì)被nop指令所代替,! early_init()函數(shù)調(diào)用identify_cpu()函數(shù)通過cpu中的pvr寄存器存放的CPU核的版本號(hào)在全局?jǐn)?shù)組cpu_specs中尋找到當(dāng)前cpu的詳細(xì)信息,,identify_cpu()函數(shù)在找到之后,會(huì)調(diào)用setup_cpu_spec()函數(shù)把上述cpu的信息所在的鏈接地址賦值給cur_cpu_spec變量
2.2 mmu_off() 關(guān)閉mmu 2.3 flush_tlbs() 從TLB中移除頁表 2.4 call_setup_cpu():call_setup_cpu()位于misc_32.S文件中 2.5 relocate_kernel():把內(nèi)核代碼拷貝到鏈接地址指向的位置 2.6 turn_on_mmu():映射了256MB內(nèi)存,,就可以避免調(diào)用reloc_offset()函數(shù)來顯式得把虛擬地址映射到物理地址! 2.7跳到start_here()函數(shù)中運(yùn)行,,可以認(rèn)為是真正內(nèi)核開始運(yùn)行。,。,。 2.7.1加載0號(hào)線程上下文,全局變量init_task 注:0號(hào)線程優(yōu)先級(jí)為120,從#define INIT_TASK(tsk)中可以看出,。 init_task是進(jìn)程0使用的進(jìn)程描述符,,也是Linux系統(tǒng)中第一個(gè)進(jìn)程描述符,該進(jìn)程的描述符在arch/powerpc/kernel/init_task.c中定義,,代碼片段如下: struct task_struct init_task = INIT_TASK(init_task); init_task描述符使用宏INIT_TASK對(duì)init_task的進(jìn)程描述符進(jìn)行初始化,,宏INIT_TASK在include/linux/init_task.h文件中 init_task是Linux內(nèi)核中的第一個(gè)線程,它貫穿于整個(gè)Linux系統(tǒng)的初始化過程中,,該進(jìn)程也是Linux系統(tǒng)中唯一一個(gè)沒有用kernel_thread() 函數(shù)創(chuàng)建的進(jìn)程,!在init_task進(jìn)程執(zhí)行后期,它會(huì)調(diào)用kernel_thread()函數(shù)創(chuàng)建第一個(gè)核心進(jìn)程kernel_init,,同時(shí)init_task進(jìn)程繼續(xù)對(duì)Linux系統(tǒng)初始化,。在完成初始化后,init_task會(huì)退化為cpu_idle進(jìn)程,,當(dāng)Core 0的就緒隊(duì)列中沒有其它進(jìn)程時(shí),,該進(jìn)程將會(huì)獲得CPU運(yùn)行。新創(chuàng)建的1號(hào)進(jìn)程kernel_init將會(huì)逐個(gè)啟動(dòng)次CPU,并最終創(chuàng)建用戶進(jìn)程,! 備注:core0上的idle進(jìn)程由init_task進(jìn)程退化而來,,而AP的idle進(jìn)程則是BSP在后面調(diào)用fork()函數(shù)逐個(gè)創(chuàng)建的,我們會(huì)在后面詳細(xì)討論,。 init_task進(jìn)程使用init_thread_union數(shù)據(jù)結(jié)構(gòu)描述的內(nèi)存區(qū)域作為該進(jìn)程的堆??臻g,并且和自身的thread_info參數(shù)公用這一內(nèi)存空間空間,,其數(shù)據(jù)結(jié)構(gòu)的定義如下(linux- 2.6.38/include/linux/sched.h) 2.7.2 調(diào)用machine_init()分析OF樹的結(jié)構(gòu),,獲得當(dāng)前處理器的內(nèi)存使用情況, 創(chuàng)建LMB結(jié)構(gòu),同時(shí)獲得當(dāng)前CPU在OF樹中的硬件信息;保存命令行等,,從cmd_line拷貝uboot引導(dǎo)kernel時(shí)使用的命令行參數(shù)到boot_command_line,,并并使用parse_early_param()函數(shù)分析這些命令行參數(shù)。
2.7.3 調(diào)用MMU_init(),,為LinuxPowerPC建立MMU地址映射,,區(qū)分memory 的normal 區(qū)域和高端區(qū)域。(768M或896M為分界線) 注:會(huì)把也映射信息更新到init_mm. pgd,,即swapper_pg_dir指向的頁表中,。最終應(yīng)該會(huì)把init_mm填到init1 線程任務(wù)結(jié)構(gòu)的mm_struct中。需要后續(xù)驗(yàn)證*********************** ***************************************************************************************************************************************** 2.7.4 調(diào)用load_up_mmu()重新裝載MMU相關(guān)的寄存器,,開啟MMU并跳到start_kernel 再次讓CPU進(jìn)入是實(shí)地址模式,,去運(yùn)行load_up_mmu()函數(shù)。這樣做的目的是讓core 0在實(shí)模式下調(diào)用load_up_mmu()函數(shù)來重新裝載MMU相關(guān)的寄存器,,比如SDR1,,BAT寄存器等。之所以要重新轉(zhuǎn)載,是因?yàn)槲覀冊?/span><11>:bl initial_bats,,創(chuàng)建的臨時(shí)BAT塊地址映射,,只是啟動(dòng)的第一階段用到的臨時(shí)映射,現(xiàn)在這個(gè)臨時(shí)地址映射需要舍棄了,,我們需要重新初始化MMU,來建立正式的MMU地址映射,。
注:從__start()到start_here()再到調(diào)用start_kernel(),,主要的工作與當(dāng)前目標(biāo)板的硬件結(jié)構(gòu)密切相關(guān),包含對(duì)一些底層硬件進(jìn)行最基本初始化操作等等,,從start_kernel()開始的初始化操作與處理器的類型基本無關(guān)了,。
3 start_kernel 本階段也是有0號(hào)線程init_task中調(diào)用的,將完成Linux內(nèi)核核心數(shù)據(jù)結(jié)構(gòu)的初始化,,最終創(chuàng)建1號(hào)線程kernel_init,,最后由1號(hào)內(nèi)核線程啟動(dòng)1號(hào)用戶進(jìn)程。需要后續(xù)確認(rèn)***
3.1 關(guān)中斷 3.2 調(diào)用tick_init(),,初始化系統(tǒng)時(shí)鐘滴答鏈 3.3 調(diào)用page_address_init(),,將高端內(nèi)存組織在一起。應(yīng)該是為buddy初始化做準(zhǔn)備,,需要進(jìn)一步確認(rèn) 3.4 setup_arch(),,setup_arch()函數(shù)是start_kernel()中非常重要函數(shù),主要作用是對(duì)內(nèi)存進(jìn)行初始化后,,調(diào)用ppc_md結(jié)構(gòu)的setup_arch()函數(shù)對(duì)當(dāng)前目標(biāo)板系統(tǒng)進(jìn)行基本的初始化,。 3.4.1 unflatten_device_tree(),check_for_initrd();對(duì)OF Tree和initrd進(jìn)行檢查 3.4.2 find_legacy_serial_ports(),,對(duì)串口進(jìn)行檢查和設(shè)置 3.4.3 register_early_udbg_console()對(duì)調(diào)試口進(jìn)行檢查和設(shè)置 3.4.4設(shè)置指令和數(shù)據(jù)cache的長度 3.4.5 Linux系統(tǒng)進(jìn)入Panic后,,180秒后重啟系統(tǒng) 3.4.6設(shè)置0號(hào)進(jìn)程mm_struct結(jié)構(gòu)的代碼段,數(shù)據(jù)段和堆棧段 3.4.7 irqstack_early_init();//初始化中斷棧,,需要進(jìn)一步研究 3.4.8 do_init_bootmem();//初始化Boot Memory 3.4.9 ppc_md.setup_arch()對(duì)具體的處理器系統(tǒng)進(jìn)行初始化,,不同的處理器系統(tǒng)使用不同的ppc_md.setup_arch()函數(shù),該函數(shù)在probe_machine()函數(shù)中設(shè)置 3.4.10 paging_init(),,初始化ZONE_DMA,,ZONE_NORMAL和ZONE_HIGHMEM區(qū)域的空閑頁表相關(guān),需要后續(xù)深入理解************************************* 3.5 setup_command_line(command_line)該函數(shù)對(duì)命令行參數(shù)進(jìn)行處理 注:命令行參數(shù)保存到全局?jǐn)?shù)組中,,見定義:char cmd_buf[256]; char *cmd_line = cmd_buf; 3.6 setup_per_cpu_areas()該函數(shù)初始化每個(gè)CPU的專用數(shù)據(jù)區(qū)域
3.7 smp_prepare_boot_cpu():它設(shè)置當(dāng)前BSP有效,,設(shè)置current_set數(shù)組中下標(biāo)為boot_cpuid的指針指向0號(hào)進(jìn)程init_task的thread_info描述符。 struct thread_info *current_set[NR_CPUS];
注:struct thread_info和struct task_struct間的關(guān)系,,參見下面的數(shù)據(jù)結(jié)構(gòu) union thread_union { struct thread_info thread_info; unsigned long stack[THREAD_SIZE/sizeof(long)]; }; union thread_union init_thread_union; 即init_task->stack 就是init_thread_union的起始地址,。 而thread_union中的前12個(gè)字是thread_info和stack共用的,其實(shí)是thread_info利用了stack(8192B)的低地址的一部分空間而已。Stack 會(huì)從高地址向低地址方向使用,。 問題:只有init_task這樣用,?還是所有的線程都這樣用法?,?,?need confirmation
3.8 build_all_zonelists()該函數(shù)調(diào)用__build_all_nozelists函數(shù)初始化每個(gè)CPU的存儲(chǔ)節(jié)點(diǎn),并根據(jù)Linux PowerPC提供的數(shù)據(jù)區(qū)域,,如ZONE_DMA和ZONE_HIMEM來劃分內(nèi)存區(qū)間,。這部分的初始化也被稱之為存儲(chǔ)節(jié)點(diǎn)的初始化。 3.9 page_alloc_init()該函數(shù)為系統(tǒng)設(shè)置一個(gè)page_alloc_cpu_notify回調(diào)函數(shù),,該函數(shù)用來實(shí)現(xiàn)CPU的關(guān)閉與使能,。在一個(gè)MPP結(jié)構(gòu)的處理器系統(tǒng)或者大型服務(wù)器中有大量的CPU,該函數(shù)可以臨時(shí)打開或者關(guān)閉某些Core或者CPU,,此時(shí)Linux系統(tǒng)會(huì)調(diào)用page_alloc_cpu_notify函數(shù),,但是在我們的針對(duì)MPC8641HPCN平臺(tái),linux-smp沒有該功能,,page_alloc_init()為空,! 3.10 parse_early_param()和parse_args():這兩個(gè)函數(shù)解析UBoot傳到給Linux內(nèi)核的一些參數(shù)。
3.11 vfs_caches_init_early();初始化VFS系統(tǒng)使用的dentry和inode結(jié)構(gòu)專用SLAB描述符,,Linux使用dentry結(jié)構(gòu)保存有關(guān)文件目錄的信息,,使用inode結(jié)構(gòu)保存有關(guān)文件的信息。 3.12 sort_main_extable()該函數(shù)對(duì)異常調(diào)用表進(jìn)行重新排序,,Linux系統(tǒng)將異常調(diào)用表放在__ex_table調(diào)用表中,。
3.13 mm_init():該函數(shù)是一個(gè)靜態(tài)的函數(shù),它調(diào)用mem_init()函數(shù)初始化所有的頁表描述符,并初始化Buddy System,;然后調(diào)用kmem_cache_init()函數(shù)初始化Linux系統(tǒng)的SLAB分配器,。
3.14 sched_init():初始化主調(diào)度器的運(yùn)行隊(duì)列rq,在Linux SMP系統(tǒng)中每一個(gè)CPU都有自己的運(yùn)行隊(duì)列,! 3.16 preempt_disable():正如代碼注釋所說的那樣,,現(xiàn)在是禁用進(jìn)程搶占功能的,因?yàn)槟壳暗恼{(diào)度器還比較脆弱,,只有執(zhí)行了cpu_idle()函數(shù)之后才能進(jìn)行進(jìn)程搶占功能,! 3.17 idr_init_cache():該函數(shù)的初始化idr_layer_cache結(jié)構(gòu)的SLAB分配器,idr ,?,??,?,? Linux基數(shù)樹(radix tree),,ID radix。IDR(ID Radix)機(jī)制是將對(duì)象的身份鑒別號(hào)整數(shù)值ID與對(duì)象指針建立關(guān)聯(lián)表,,完成從ID與指針之間的相互轉(zhuǎn)換,。IDR機(jī)制使用radix樹狀結(jié)構(gòu)作為由id進(jìn)行索引獲取指針的稀疏數(shù)組,通過使用位圖可以快速分配新的ID,,IDR機(jī)制避免了使用固定尺寸的數(shù)組存放指針,。 可以認(rèn)為IDR機(jī)制是一種可伸展的數(shù)組的機(jī)制,并且?guī)?/span>bitmask,。
3.18 rcu_init():初始化Linux PowerPC的RCU部件,,RCU是一種鎖機(jī)制
3.19 radix_tree_init():使用idr_init_cache()分配的Slab cache初始化radix樹。 3.20 init_IRQ (),,調(diào)用ppc_md.init_IRQ()初始化IRQ,需要跟進(jìn)理解 3.21 init_timers():初始化linux系統(tǒng)使用的定時(shí)器 3.22 hrtimers_init():初始化高精度定時(shí)器,,與Linux 系統(tǒng)提供的標(biāo)準(zhǔn)定時(shí)器相比,,該定時(shí)器更為準(zhǔn)確。 3.23 softirq_init():對(duì)Linux系統(tǒng)軟件中斷進(jìn)行初始化 3.24 time_init(): 初始化Linux系統(tǒng)的定時(shí)器,,Linux PowerPC可以使用外部RTC作為系統(tǒng)的定時(shí)器,,也可以使用TB寄存器! 3.25 local_irq_enable():開中斷 3.26 console_init():初始化控制器console,,console是Linux系統(tǒng)用于輸出一些監(jiān)控信息的設(shè)備,,Linux系統(tǒng)一般使用串口或者監(jiān)視器作為console設(shè)備! 3.27 setup_per_cpu_pageset():初始化當(dāng)前CPU(即BSP)每一個(gè)數(shù)據(jù)區(qū),,如ZONE_DMA,ZONE_HIMEM使用per_cpu_pageset緩沖 3.28 pidmap_init():建立pid結(jié)構(gòu)使用的專用Cache描述符表pid_cachep 3.29 fork_init(totalram_pages):創(chuàng)建task_struct結(jié)構(gòu)專用的Slab Cache描述符task_struct_cachep,并確定當(dāng)前Linux系統(tǒng)所能容納的最大進(jìn)程數(shù)目max_threads 3.30 proc_caches_init():創(chuàng)建專用的Slab Cache描述符sighand_cachep,、signal_cachep、files_cachep,、fs_cachep,、mm_cachep、vm_area_cachep,。 3.31 buffer_init():創(chuàng)建buffer_head結(jié)構(gòu)的專用Slab Cache描述符bh_cachep,linux的文件系統(tǒng)使用buffer_head結(jié)構(gòu)保存來自外部設(shè)備的數(shù)據(jù),。 3.32 vfs_caches_init(totalram_pages):創(chuàng)建專用的Slab cache描述符names_cachep和filp_cachep,然后調(diào)用 dcache_init()、inode_init(),、files_init(mempages),、mnt_init()、bdev_cache_init()和chrdev_init()函數(shù)對(duì)Linux文件系統(tǒng)的各個(gè)子系統(tǒng)進(jìn)行初始化,。 3.33 signals_init():創(chuàng)建信號(hào)專用的Slab cache描述符sigqueue_cachep,,并初始化Linux系統(tǒng)的信號(hào)機(jī)制 3.34 page_writeback_init():初始化文件系統(tǒng)的回調(diào)函數(shù),Linux文件系統(tǒng)中會(huì)有很多“臟”頁,,這些頁不會(huì)立即和存儲(chǔ)系統(tǒng)中的數(shù)據(jù)進(jìn)行同步,,只有在需要進(jìn)行同步時(shí)才調(diào)用這些回調(diào)函數(shù)進(jìn)行同步,。 3.35 proc_root_init():創(chuàng)建根文件系統(tǒng),其實(shí)是根據(jù)數(shù)據(jù)結(jié)構(gòu)proc_fs_type,,mount 文件系統(tǒng),,并創(chuàng)建相應(yīng)的文件夾。沒看到根文件系統(tǒng)相關(guān),,從注釋到函數(shù)名都顯示是proc文件系統(tǒng),。不知何故?,?,??,? 3.36 調(diào)用rest_init()函數(shù),。
4. rest_init()函數(shù)。
4.1 調(diào)用kernel_thread()創(chuàng)建1號(hào)內(nèi)核線程,。 4.2 調(diào)用kernel_thread()創(chuàng)建kthreadd內(nèi)核線程,。尚不明作用。 4.3 init_idle_bootup_task():當(dāng)前0號(hào)進(jìn)程init_task最終會(huì)退化成idle進(jìn)程,,所以這里調(diào)用init_idle_bootup_task()函數(shù),,讓init_task進(jìn)程隸屬到idle調(diào)度類中。即選擇idle的調(diào)度相關(guān)函數(shù),。 4.4 調(diào)用schedule()函數(shù)切換當(dāng)前進(jìn)程,,在調(diào)用該函數(shù)之前,Linux系統(tǒng)中只有兩個(gè)進(jìn)程,,即0號(hào)進(jìn)程init_task和1號(hào)進(jìn)程kernel_init,,其中kernel_init進(jìn)程也是剛剛被創(chuàng)建的。調(diào)用該函數(shù)后,,1號(hào)進(jìn)程kernel_init將會(huì)運(yùn)行,! 4.5 調(diào)用cpu_idle(),0號(hào)線程進(jìn)入idle函數(shù)的循環(huán),,在該循環(huán)中會(huì)周期性地檢查,。
5 kernel_init 1號(hào)線程初始化 主要包括三方面 第一:引導(dǎo)SMP系統(tǒng)中的其它CPU(即AP(Aplication Processor)) 第二:調(diào)用do_basic_setup()函數(shù),完成Linux系統(tǒng)其它模塊的初始化,; 第三:更換核心進(jìn)程kernel_init為普通進(jìn)程之后,,完成對(duì)Linux系統(tǒng)的二次引導(dǎo),即對(duì)Linux系統(tǒng)應(yīng)用程序的引導(dǎo),!
5.1設(shè)置當(dāng)前1號(hào)線程所允許的BSP(即core 0)在cpu_all_mask中的對(duì)應(yīng)bit位 5.2 init_pid_ns.child_reaper = current; 設(shè)置1號(hào)線程回收orphan 線程,。1號(hào)進(jìn)程在Linux系統(tǒng)中相當(dāng)于一個(gè)收容所,專門用于處理那些孤兒進(jìn)程,。 5.3 smp_prepare_cpus(setup_max_cpus)該函數(shù)的作用是首先探測我們的目標(biāo)系統(tǒng)中有多少個(gè)CPU,,該函數(shù)為每個(gè)CPU創(chuàng)建一個(gè)idle進(jìn)程,。 5.4 smp_init()是我們的linux-smp映像中啟動(dòng)另外一個(gè)核的最重要的代碼,該函數(shù)主要是引導(dǎo)SMP系統(tǒng)中的AP,,該函數(shù)會(huì)依次調(diào)用:smp_init()-> cpu_up()-> _cpu_up()-> __cpu_up()-> smp_ops-> kick_cpu(kick_cpu是一個(gè)函數(shù)指針,,指向smp_86xx_kick_cpu,故會(huì)執(zhí)行smp_86xx_kick_cpu()函數(shù))smp_86xx_kick_cpu()-> smp_86xx_release_core()-> __secondary_start_mpc86xx()-> __secondary_start()來啟動(dòng)core 1,,并調(diào)用set_cpu_online()函數(shù)將次CPU加入到cpu_online_map變量中,用以向主CPU通知該次CPU已經(jīng)被激活,。 5.5 sched_init_smp()該函數(shù)的作用,有待遇進(jìn)一步的分析,! 5.6 do_basic_setup():到目前為止,,內(nèi)核已經(jīng)初始化了,memory管理和process scheduler 已經(jīng)開始運(yùn)行,。但尚未注冊設(shè)備,。在本函數(shù)中將初始化workqueue,初始化device drivers,,初始化中斷處理,,最后調(diào)用do_initcalls()進(jìn)行靜態(tài)安裝所有模塊,其中包括驅(qū)動(dòng)人員最關(guān)心的用device_initcall聲明的設(shè)備模塊的安裝,。
5.7 調(diào)用init_post()創(chuàng)建用戶模式1號(hào)進(jìn)程。
第三步:Linux的應(yīng)用程序的初始化 1號(hào)kernel_init進(jìn)程完成linux的各項(xiàng)配置(包括啟動(dòng)AP)后,,就會(huì)在/sbin,/etc,/bin尋找init程序來運(yùn)行,。該init程序會(huì)替換kernel_init進(jìn)程(注意:并不是創(chuàng)建一個(gè)新的進(jìn)程來運(yùn)行init程序,而是一次變身,,使用sys_execve函數(shù)改變核心進(jìn)程的正文段,,將核心進(jìn)程kernel_init轉(zhuǎn)換成用戶進(jìn)程init),此時(shí)處于內(nèi)核態(tài)的1號(hào)kernel_init進(jìn)程將會(huì)轉(zhuǎn)換為用戶空間內(nèi)的1號(hào)進(jìn)程init,。戶進(jìn)程init將根據(jù)/etc/inittab中提供的信息完成應(yīng)用程序的初始化調(diào)用,。然后init進(jìn)程會(huì)執(zhí)行/bin/sh產(chǎn)生shell界面提供給用戶來與Linux系統(tǒng)進(jìn)行交互。 調(diào)用init_post()創(chuàng)建用戶模式1號(hào)進(jìn)程,。 在init_post()中最終調(diào)用下面的任何一個(gè)入口(按順序,,第一個(gè)執(zhí)行成功后將不返回) if (execute_command) { run_init_process(execute_command); printk(KERN_WARNING "Failed to execute %s. Attempting " "defaults...\n", execute_command); } run_init_process("/sbin/init"); run_init_process("/etc/init"); run_init_process("/bin/init"); run_init_process("/bin/sh");
|
|