Linux內核的啟動過程分析

秦鼎濤 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 

一、實驗目的及要求:

  • 使用gdb跟蹤調試內核從start_kernel到init進程啟動

  • 詳細分析從start_kernel到init進程啟動的過程并結合實驗截圖撰寫一篇署名博客,并在博客文章中注明“真實姓名(與最后申請證書的姓名務必一致) + 原創作品轉載請注明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000?”,博客內容的具體要求如下:

    • 題目自擬,內容圍繞Linux內核的啟動過程,即從start_kernel到init進程啟動;

    • 博客中需要使用實驗截圖

    • 博客內容中需要仔細分析start_kernel函數的執行過程

    • 總結部分需要闡明自己對“Linux系統啟動過程”的理解,尤其是idle進程、1號進程是怎么來的。

  • 3)請提交博客文章URL到網易云課堂MOOC平臺Linux內核分析MOOC課程,編輯成一個鏈接可以直接點擊打開。? 

二、實驗步驟(含實驗樓截圖):

  1、登陸實驗樓虛擬機

    打開shell終端,執行以下命令:

    cd LinuxKernel/

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootfs.img

    

(系統支持三個命令:help、version、quit)

  2、使用gdb跟蹤調試內核

  執行以下命令:

  cd LinuxKernel/

  qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootfs.img -s -S

  關于-s和-S選項的說明:

  -S freeze CPU at startup (use ’c’ to start execution) 在系統啟動的時候凍結CPU,使用c鍵繼續執行后續操作

  -s shorthand for -gdb tcp::1234 打開遠程調試端口,默認使用tcp協議1234端口,若不想使用1234端口,則可以使用-gdb tcp:xxxx來取代-s選項

  

?

  打開另外一個shell終端,執行以下命令

  gdb

  (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加載符號表

  (gdb)target remote:1234 # 建立gdb和gdbserver之間的連接,按c 讓qemu上的Linux繼續運行

  (gdb)break start_kernel # 斷點的設置可以在target remote之前,也可以在之后

  

  (不知道為什么沒有找到文件目錄。。)

?

三、start_kernel函數的執行過程分析:

asmlinkage void __init start_kernel(void)

{
?char * command_line;
?extern struct kernel_param __start___param[], __stop___param[];
/*
?* Interrupts are still disabled. Do necessary setups, then
?* enable them
?*/
?lock_kernel();
如果內核配置成支持搶占,那么在這里禁止搶占,將0號進程的init_thread_info.preempt_count加1;
如果配置成不支持搶占,那么內核全局自選鎖kernel_flag上鎖。
?page_address_init();
10版本的ARM部分,沒有支持高端內存相關代碼,空函數。
?printk(linux_banner);
將linux_banner的內容打印到log_buf緩沖區中。
?setup_arch(&command_line);
函數原型在arch/arm/kernel/setup.c中
根據處理器、硬件平臺具體型號設置系統。解析Linux系統命令行,設置0號進程(swapper進程)的內存描述結構init_mm,系統內存管理初始化,統計并注冊系統各種資源,其他項目的初始化。
?setup_per_cpu_areas();
為系統中每個處理器的per_cpu變量申請空間。
/*
? * Mark the boot cpu "online" so that it can call console drivers in
? * printk() and can access its per-cpu storage.
? */
?smp_prepare_boot_cpu();
/*
? * Set up the scheduler prior starting any interrupts (such as the
? * timer interrupt). Full topology setup happens at smp_init()
? * time - but meanwhile we still have a functioning scheduler.
? */
?sched_init();
初始化每個處理器的可運行進程隊列,設置系統初始化進程即0號進程。
?build_all_zonelists();
建立系統內存頁區(zone)鏈表。
?page_alloc_init();
?printk("Kernel command line: %s\n", saved_command_line);
?parse_early_param();
解析早期格式內核參數。
?parse_args("Booting kernel", command_line, __start___param,
???? __stop___param - __start___param,
???? &unknown_bootoption);
解析新格式內核參數。
?sort_main_extable();
將放在__start__ex_table到__stop__ex_table之間的*(__ex_table)區中的struct exception_table_entry型全局結構變量按insn成員變量值從小到大排序,即將可能導致缺頁異常的指令按其指令二進制代碼值從小到大排序。
?trap_init();
把放在.Lcvectors處的系統8個意外的入口跳轉指令搬到高端中斷向量0xffff0000處,再將從__stubs_start到__stubs_end之間的各種意外初始處理代碼搬到0xffff0200處。刷新0xffff0000處1頁范圍的指令cache,將DOMAIN_USER的訪問權限由DOMAIN_MANAGER權限改設置成DOMAIN_CLIENT權限。
?rcu_init();
初始化當前CPU的讀、復制、更新數據結構(struct rcu_data)全局變量per_cpu_rcu_data和per_cpu_rcu_bh_data。
?init_IRQ();
初始化系統中支持的最大可能中斷數的中斷描述結構struct irqdesc變量數組irq_desc[NR_IRQS],把每個結構變量irq_desc[n]都初始化為預先定義好的壞中斷描述結構變量bad_irq_desc,并初始化該中斷的連表表頭成員結構變量pend.
?pidhash_init();
設置系統中每種pid hash表中的hash鏈表數的移位值全局變量pidhash_shift,將pidhash_shift設置為min(12);分別為每種hash表的連續hash鏈表表頭結構空間申請內存,把申請到的內存虛擬基址分別傳給pid_hash[n](n=0~3),并將每種hash表中的每個hash鏈表表頭結構struct hlist_head中的first成員指針設置成NULL
?init_timers();
初始化當前出處理器的時間向量基本結構struct tvec_t_base_s全局變量per_cpu_tvec_bases,初始化per_cpu_tvec_bases的自旋鎖成員變量lock。
?softirq_init();
設置系統小任務軟件中斷行為函數描述結構變量softirq_vec[TASKLET_SOFTIRQ(=6)],將softirq_vec[6]的行動函數指針action指向tasklet_action()函數,參數指針設置為NULL.
?time_init();
檢查系統定時器描述結構struct sys_timer全局變量system_timer是否為空,如果是將其指向dummy_gettimeoffset()函數。
/*
? * HACK ALERT! This is early. We're enabling the console before
? * we've done PCI setups etc, and console_init() must be aware of
? * this. But we do want output early, in case something goes wrong.
? */
?console_init();
初始化系統的控制臺結構,該函數執行后調用printk()函數將log_buf中符合打印級別要求的系統信息打印到控制臺上。
?if (panic_later)
??panic(panic_later, panic_param);
?profile_init();
對系統剖析作相關初始化,系統剖析用于系統調用。
?local_irq_enable();
將處理器的當前系統狀態寄存器CPSR的第7位清0,使能IRQ中斷。
#ifdef CONFIG_BLK_DEV_INITRD
?if (initrd_start && !initrd_below_start_ok &&
???initrd_start < min_low_pfn << PAGE_SHIFT) {
??printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
????? "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
??initrd_start = 0;
?}
#endif
?vfs_caches_init_early();
?mem_init();
該函數執行完后不能再用像alloc_bootmem()、alloc_bootmem_low()、alloc_bootmem_pages()等申請低端內存的函數來申請內存,也就不能申請大塊的連續物理內存了。
?kmem_cache_init();
執行高速緩存內存管理即slab分配器相關初始化。
?numa_policy_init();
?if (late_time_init)
??late_time_init();
?calibrate_delay();
計算機系統的BogMIPS數值,即處理器每秒鐘執行的指令數。
?pidmap_init();
?pgtable_cache_init();
?prio_tree_init();
初始化無符號長整型全局數組index_bits_to_maxindex[BITS_PER_LONG]的每個組員,將每個組員index_bits_to_maxindex[n]設置成-1,將最后的index_bits_to_maxindex[BITS_PER_LONG-1]設置成~0UL。
?anon_vma_init();
該函數調用kmem_cache_create()函數,為匿名虛擬內存區域鏈表結構struct anon_vma創建高速緩存內存描述結構kmem_cache_t變量,為該變量命名為“anon_vma",其對象的構造函數指針指向void anon_vma_ctor(void *data,kmem_cache_t *cachep,unsigned long flags)函數,析構函數指針空,將創建的kmem_cache_t結構變量地址傳給全局指針anon_vma_chachep。
#ifdef CONFIG_X86
?if (efi_enabled)
??efi_enter_virtual_mode();
#endif
?fork_init(num_physpages);
執行進程創建相關初始化。
?proc_caches_init();
?buffer_init();
調用 kmem_cache_create("buffer_head",?sizeof(struct buffer_head), 0,?SLAB_PANIC, init_buffer_head, NULL)函數為緩沖區描述結構struct buffer_head創建高速緩存內存描述結構kmem_cache_t變量。
?unnamed_dev_init();
調用并返回idr_init(&unnamed_dev_idr)函數。
?security_init();
打印”安全架構v1.0.0被初始化“。如果沒有定義系統啞元安全操作函數組結構全局變量dummy_security_ops,打印錯誤信息,返回I/O錯誤。
?vfs_caches_init(num_physpages);
?radix_tree_init();
?signals_init();
調用kmem_cache_create("sigqueue",?sizeof(struct sigqueue),?__alignof__(struct sigqueue),?SLAB_PANIC, NULL, NULL)函數為信號隊列結構struct sigqueue創建高速緩存內存描述結構kmem_cache_t變量,名字叫”sigqueue“,不要求其對象按處理器硬件cache line大小對齊,沒有定義其對象的構造和析構函數,將創建號的kmem_cache_t結構變量的地址傳給全局指針sigqueue_cachep。
?/* rootfs populating might need page-writeback */
?page_writeback_init();
統計系統中所有內存節點的通用(NORMAL)內存頁區中高頁數水印值頁數之外的額外內存總頁數之和傳給buffer_pages。
#ifdef CONFIG_PROC_FS
?proc_root_init();
只有在系統支持proc文件系統即配置了CONFIG_PROC_FS選項時才被調用。
#endif
?check_bugs();
acpi_early_init(); /* before LAPIC and SMP init */
/* Do the rest non-__init'ed, we're now alive */
?rest_init();
該函數創建init()內核進程即1號進程,然后是系統啟動進程即0號進程空閑。
}

?

四、實驗總結:

   當計算機電源啟動,BIOS代碼被調用執行,然后開始調用執行Linux內核初始化代碼,在平臺相關的匯編代碼

執行完畢后會跳轉到start_kernel()函數,開始真正的內核初始化,其中init_task創建了0號進程,即最終的idle進程,

隨后rest_init()函數創建了init進程,即1號進程,以及kthreadd進程,即2號進程,系統開始正式對外工作了。

?

轉載于:https://www.cnblogs.com/qindingtao/p/5268143.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375004.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375004.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375004.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

static修飾符詳解

static表示“全局”或者“靜態”的意思&#xff0c;用來修飾成員變量和成員方法&#xff0c;也可以形成靜態static代碼塊&#xff0c;但是Java語言中沒有全局變量的概念。被static修飾的成員變量和成員方法獨立于該類的任何對象。也就是說&#xff0c;它不依賴類特定的實例&…

四則運算2+psp0

程序要求&#xff1a; 1.題目避免重復 2.可定制&#xff08;數量\打印方式&#xff09; 3.可以一下控制參數 ① 是否有乘除法 ② 是否有括號&#xff08;最多支持十個數參與運算&#xff09; ③ 數值范圍 ④加減有無負數 ⑤除法有無余數 分析&#xff1a;① 如果是兩個數…

kettle作業中的js如何寫日志文件

在kettle作業中JavaScript腳本有時候也扮演非常重要的角色&#xff0c;此時我們希望有一些日志記錄。下面是job中JavaScript記錄日志的方式。 job的js寫日志的方法。 得到日志輸出實例 org.pentaho.di.core.logging.LogWriter.getInstance();按照日志的級別輸出&#xff1a; pu…

淺析Kerberos原理,及其應用和管理

文章作者&#xff1a;luxianghao 文章來源&#xff1a;http://www.cnblogs.com/luxianghao/p/5269739.html 轉載請注明&#xff0c;謝謝合作。 免責聲明&#xff1a;文章內容僅代表個人觀點&#xff0c;如有不當&#xff0c;歡迎指正。 --- 一&#xff0c;引言 Kerberos簡單來…

2014! 的末尾有多少個0

2014&#xff01; 的末尾有多少個0<?xml version"1.0" encoding"UTF-8"?> 假設 末尾有 k 個0&#xff0c;所以 2014&#xff01; x * 10^k ; 10 ^ k &#xff08;2 * 5 &#xff09;^ k 2^k * 5^k, 明顯所有數字中因數含有2的數字多于含有5的數…

[轉載]一句話插配置文件

http://www.t00ls.net/viewthread.php?tid13901 一句話插入配置文件system.asp沒有過濾雙引號&#xff0c;插入一句就行。常規插法如下&#xff1a;"%><%eval request("d")%><%但金刀客這篇文件&#xff08;http://www.cqzh.cn/post/328.html&…

android插件化-獲取apkplug框架已安裝插件-03

上一篇文章成功的將apkplug框架嵌入了應用中而且啟動 鏈接http://www.apkplug.com/blog/?post10 這一篇文章實現怎樣獲取全部已安裝插件 一 獲取框架的SystemBundle的上下文BundleContext apkplug框架啟動會自己主動創建一個SystemBundle, 它是框架的第一個插件不可停止和卸…

Java實現棧。

定義一個接口MyStack接口&#xff1a; package Stack; public interface MyStack<T> { boolean isEmpty(); int length(); boolean push(T date); T pop();} 數組實現&#xff1a; package Stack; public class ArrayStack<T> implements MyStack<T>{ privat…

轉載]SA權限九種上傳方法

剛看了一種方法&#xff0c;如果是注入點&#xff0c;利用管中窺豹以二進制的方式上傳&#xff0c;上傳的時候最好改下名&#xff0c;比如do.exe&#xff0c;上傳到目標服務器可以改成do.cmd&#xff0c;等傳上去之后用copy 命令改回來。 當然用啊d也可以上傳&#xff0c;還有…

asp.net 導出Excel

asp.net 導出Excel 分享一個asp.net 導出假Excel代碼。優點&#xff0c;不用借助于任何插件比如&#xff08;NPOI&#xff09;,復制代碼&#xff0c;修改grid.DataSource直接導出。 先看導出后的效果圖 1 System.Web.UI.WebControls.DataGrid grid new DataGrid();2 …

bzoj 2300 動態維護上凸殼(不支持刪除)

新技能GET。 用set保存點&#xff0c;然后只需要找前趨和后繼就可以動態維護了。 1 /**************************************************************2 Problem: 23003 User: idy0024 Language: C5 Result: Accepted6 Time:556 ms7 Memory:4824 kb8 …

帶有Guice的富域模型

貧血域模型是一個非常常見的反模式。 在ORM和DI框架的世界中&#xff0c;我們自然會發現自己擁有一個由ORM管理的“域”&#xff0c;該域包含所有數據且無行為。 通過我們的DI框架有幫助地注入了輔助類&#xff0c;這些輔助類都是行為且沒有數據。 在本文中&#xff0c;我將介紹…

php匿名函數小示例

<?php //$fun function($params){ // echo $params; //}; // //$fun(aa);//例一 //在普通函數中定義一個匿名函數 //function printStr(){ // $fun function($something){ // echo $something; // }; // $fun(something); // //} //printStr();//例子…

購書心得

作者&#xff1a;泉哥主頁&#xff1a;http://riusksk.blogbus.com富家不用買良田&#xff0c;書中自有千鐘粟&#xff1b;安居不用架高堂&#xff0c;書中自有黃金屋&#xff1b;出門莫恨無人隨&#xff0c;書中車馬多如簇&#xff1b;娶妻莫恨無良媒&#xff0c;書中自有顏如…

MariaDB?條件語句WHERE

MariaDB 條件語句WHEREWHERE Clause Operators Operator Description Equality<> Nonequality! Nonequality< Less than< Less than or equal to > Greater than > Greater than or equal to BETWEEN Between two specified values BETWEEN AND (jlive)[c…

Spring 3.1緩存抽象教程

即將發布的Spring 3.1版本中引入的新功能之一是緩存抽象之一 。 Spring Framework提供了對將緩存透明添加到現有Spring應用程序中的支持。 與事務支持類似&#xff0c;緩存抽象允許一致使用各種緩存解決方案&#xff0c;而對代碼的影響最小。 從本質上講&#xff0c;抽象將緩存…

《Linux內核分析》 第四節 扒開系統調用的三層皮(上)

黃胤凱 原創作品轉載請注明出處 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 一、視頻學習 1.系統調用的三層皮&#xff1a;xyz system_call sys_xyz 對應的是API&#xff0c;中斷向量對應的中斷服務程序&#xff0c;系統調用服務程…

如何在Java中獲得類似于C的性能

總覽 Java有許多可能很慢的領域。 但是&#xff0c;對于每個問題都有解決方案。 許多解決方案/黑客都需要解決Java的保護問題&#xff0c;但是如果您需要低水平的性能&#xff0c;還是可以的。 Java使高級編程變得更簡單容易&#xff0c;但代價是使低級編程變得更加困難。 幸…

STARTUPINFO結構

1.結構原型 typedef struct _STARTUPINFO { DWORD cb; LPTSTR lpReserved; LPTSTR lpDesktop; LPTSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD w…