天天看點

kernel啟動過程的三個特殊程序

  • Linux下有3個特殊的程序,分别是idle程序、init程序、kthreadd程序

idle程序

  1. [linux]程序(三)——idle程序
  2. Linux下0号程序的前世(init_task程序)今生(idle程序)—-Linux程序的管理與排程(五)
  • idle程序(PID = 0):其前身為init_task程序,該由系統自動建立, 運作在核心态,是系統建立的第一個程序,也是唯一一個沒有通過fork或者kernel_thread産生的程序。完成加載系統後,先後建立kernel_init(該程序最終演變為init程序)和kthreadd程序,并最終演變為idle程序。
  • idle程序的作用:idle程序不參與程序排程機制,當系統中沒有任何程序可以排程(就緒隊列為空)時,cpu就會進入該程序 —— 也就是說當系統沒事幹的時候就執行它,其存在的目的是為了讓排程器一直處于運作狀态(要不然所有的程序全挂起了排程器就會空閑下來)。
    系統的空閑時間,其實就是指idle程序的”運作時間”
  • 在多核系統中,每個處理器單元都有獨立的一個運作隊列,而每個運作隊列上又有一個idle程序 —— 是以有多少cpu,就有多少idle程序。

idle程序的演化

  1. Linux在無程序概念的情況下從初始化部分的代碼一直執行到調用

    start_kernel()

    函數為止,接着建立原始程序init_task(即0号線程)。
    • 原始程序:雖然程序号為0,但此時還不叫idle程序,而叫init_task程序
  2. 原始程序init_task開始執行

    start_kernel()

    完成Linux核心的初始化工作(包括初始化頁表,初始化中斷向量表,初始化系統時間等),直到執行到

    start_kernel()

    中的最後一個函數

    rest_init()

  3. 原始程序init_task在

    rest_init()

    中開始産生其它程序(即init程序和kthreadd程序),并最終退化為idle程序。
    • rest_init()

      函數的内容:
      static noinline void __init_refok rest_init(void) {
          ...
          kernel_thread(kernel_init, NULL, CLONE_FS); // 建立kernel_init程序(即1号程序),該程序最終演化為init程序
          ...
          pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);   // 建立kthreadd程序(即2号程序),該程序負責所有核心線程的排程和管理
          ...
          init_idle_bootup_task(current); // 将原始程序隸屬到idle排程類中
          schedule_preempt_disabled();    // 使1号程序kernel_init處于運作狀态
          cpu_startup_entry(CPUHP_ONLINE);    // 使得0号程序進入idle事件循環 —— 即最終演變為idle程序
      }
                 
    • rest_init()

      函數的執行步驟:
      1. 調用

        kernel_thread()

        建立1号核心程序kernel_init, 該程序随後轉向使用者空間, 并最終演變為init程序。
      2. 調用

        kernel_thread()

        建立kthreadd核心程序,該程序一直在核心中,并最終演變為kthreadd程序。
      3. 調用

        init_idle_bootup_task()

        将原始程序隸屬到idle排程類中。
      4. 調用

        schedule_preempt_disabled()

        切換目前程序,使1号程序kernel_init處于運作狀态
      5. 調用

        cpu_startup_entry()

        ,而該函數又會間接調用

        cpu_idle_loop()

        ,使得0号程序進入idle事件循環 —— 即最終演變為idle程序

init程序

  1. Linux下1号程序的前世(kernel_init)今生(init程序)—-Linux程序的管理與排程(六)
  • init程序(PID = 1):由idle通過kernel_thread建立(此時還不是init程序,而是kernel_init程序,運作在核心空間),在核心空間完成初始化後,加載init程式(該init程式會替換kernel_init程序,使得核心空間的kernel_init程序最終轉換為使用者空間内的1号程序init)。 該程序是系統中所有其它使用者程序的祖先程序(Linux中的所有使用者程序都是有init程序建立并運作的),在系統啟動完成完成後,最終變為守護程序監視系統其他程序

kthreadd程序

  1. Linux下2号程序的kthreadd–Linux程序的管理與排程(七)
  • kthreadd(PID = 2):由idle通過kernel_thread建立,并始終運作在核心空間, 負責所有核心線程的排程和管理(它的任務就是管理和排程其他核心線程kernel_thread, 會循環執行一個kthread的函數,該函數的作用就是運作kthread_create_list全局連結清單中維護的kthread, 當我們調用kernel_thread建立的核心線程會被加入到此連結清單中,是以所有的核心線程都是直接或者間接的以kthreadd為父程序 )

http://blog.leanote.com/post/[email protected]/e8672f7c86e9

繼續閱讀