linux程序 init程序(九)

2021-10-23 23:23:14 字數 3308 閱讀 3790

linux下有3個特殊的程序,idle程序(),init程序()和kthreadd()

idle程序由系統自動建立, 執行在核心態

idle程序其pid=0,其前身是系統建立的第乙個程序,也是唯一乙個沒有通過fork或者kernel_thread產生的程序。完成載入系統後,演變為程序排程、交換

init程序由idle通過kernel_thread建立,在核心空間完成初始化後, 載入init程式, 並終端使用者空間

由0程序建立,完成系統的初始化,是系統中所有其它使用者程序的祖先程序,linux中的所有程序都是有init程序建立並執行的。首先linux核心啟動,然後在使用者空間中啟動init程序,再啟動其他系統程序。在系統啟動完成完成後,init將變為守護程序監視系統其他程序。

kthreadd程序由idle通過kernel_thread建立,並始終執行在核心空間, 負責所有核心執行緒的排程和管理

它的任務就是管理和排程其他核心執行緒kernel_thread, 會迴圈執行乙個kthread的函式,該函式的作用就是執行kthread_create_list全域性鍊錶中維護的kthread, 當我們呼叫kernel_thread建立的核心執行緒會被加入到此鍊錶中,因此所有的核心執行緒都是直接或者間接的以kthreadd為父程序

我們下面就詳解分析1號程序的前世(kernel_init)今生(init程序)

linux系統中的init程序(pid=1)是除了idle程序(pid=0,也就是init_task)之外另乙個比較特殊的程序,它是linux核心開始建立起程序概念時第乙個通過kernel_thread產生的程序,其開始在核心態執行,然後通過乙個系統呼叫,開始執行使用者空間的/sbin/init程式,期間linux核心也經歷了從核心態到使用者態的特權級轉變,/sbin/init極有可能產生出了shell,然後所有的使用者程序都有該程序派生出來

前面我們了解到了0號程序是系統所有程序的先祖, 它的程序描述符init_task是核心靜態建立的, 而它在進行初始化的時候, 通過kernel_thread的方式建立了兩個核心執行緒,分別是kernel_init和kthreadd,其中kernel_init程序號為1

start_kernel在其最後乙個函式rest_init的呼叫中,會通過kernel_thread來生成乙個核心程序,後者則會在新程序環境下呼叫kernel_init函式,kernel_init乙個讓人感興趣的地方在於它會呼叫run_init_process來執行根檔案系統下的 /sbin/init等程式。

0號程序建立1號程序的方式如下

kernel_thread

(kernel_init,

null

, clone_fs)

;

我們發現1號程序的執行函式就是kernel_init, 這個函式被定義init/main.c中,如下所示

kernel_init函式將完成裝置驅動程式的初始化,並呼叫init_post函式啟動使用者空間的init程序。

由0號程序建立1號程序(核心態),1號核心執行緒負責執行核心的部分初始化工作及進行系統配置,並建立若干個用於快取記憶體和虛擬主存管理的核心執行緒。

隨後,1號程序呼叫do_execve執行可執行程式init,並演變成使用者態1號程序,即init程序。

init程序是linux核心啟動的第乙個使用者級程序。init有許多很重要的任務,比如像啟動getty(用於使用者登入)、實現執行級別、以及處理孤立程序。

它按照配置檔案/etc/initab的要求,完成系統啟動工作,建立編號為1號、2號…的若干終端註冊程序getty。

每個getty程序設定其程序組標識號,並監視配置到系統終端的介面線路。當檢測到來自終端的連線訊號時,getty程序將通過函式do_execve()執行註冊程式login,此時使用者就可輸入註冊名和密碼進入登入過程,如果成功,由login程式再通過函式execv()執行shell,該shell程序接收getty程序的pid,取代原來的getty程序。再由shell直接或間接地產生其他程序。

上述過程可描述為:0號程序->1號核心程序->1號使用者程序(init程序)->getty程序->shell程序

注意,上述過程描述中提到:1號核心程序呼叫執行init函式並演變成1號使用者態程序(init程序),這裡前者是init是函式,後者是程序。兩者容易混淆,區別如下:

kernel_init函式在核心態執行,是核心**

init程序是核心啟動並執行的第乙個使用者程序,執行在使用者態下。

一號核心程序呼叫execve()從檔案/etc/inittab中載入可執行程式init並執行,這個過程並沒有使用呼叫do_fork(),因此兩個程序都是1號程序。

當核心啟動了自己之後(已被裝入記憶體、已經開始執行、已經初始化了所有的裝置驅動程式和資料結構等等),通過啟動使用者級程式init來完成引導程序的核心部分。因此,init總是第乙個程序(它的程序號總是1)。

當init開始執行,它通過執行一些管理任務來結束引導程序,例如檢查檔案系統、清理/tmp、啟動各種服務以及為每個終端和虛擬控制台啟動getty,在這些地方使用者將登入系統。

在系統完全起來之後,init為每個使用者已退出的終端重啟getty(這樣下乙個使用者就可以登入)。init同樣也收集孤立的程序:當乙個程序啟動了乙個子程序並且在子程序之前終止了,這個子程序立刻成為init的子程序。對於各種技術方面的原因來說這是很重要的,知道這些也是有好處的,因為這便於理解程序列表和程序樹圖。init的變種很少。絕大多數linux發行版本使用sysinit(由miguel van smoorenburg著),它是基於system v的init設計。unix的bsd版本有乙個不同的init。最主要的不同在於執行級別:system v有而bsd沒有(至少是傳統上說)。這種區別並不是主要的。在此我們僅討論sysvinit。 配置init以啟動getty:/etc/inittab檔案

1號程序通過execve執行init程式來進入使用者空間,成為init程序,那麼這個init在**呢

核心在幾個位置上來查尋init,這幾個位置以前常用來放置init,但是init的最適當的位置(在linux系統上)是/sbin/init。如果核心沒有找到init,它就會試著執行/bin/sh,如果還是失敗了,那麼系統的啟動就宣告失敗了。

因此init程式是乙個可以又使用者編寫的程序, 如果希望看init程式原始碼的朋友,可以參見

ubuntu等使用deb包的系統可以通過dpkg -s檢視程式所在的包

centos等使用rpm包的系統可以通過rpm -qf檢視系統程式所在的包

Init程序和程序

1 init程序 是使用者空間的初始化程序,是使用者空間啟動的第乙個程序。使用者空間的其他所有程序都由init來管理,無需核心管理。2 程序 是程式的例項,程序有生命週期。備註 程式成為程序的過程 向核心申請記憶體空間,由核心來啟動乙個程序分配記憶體空間,程序關閉時釋放記憶體空間。3 使用者空間和核...

Linux基礎命令 init程序

init init 是所有程序的父程序,它由核心執行,可以啟動其他所有的程序。init指令在啟動時會參考 etc inittab檔案的配置,完成其他程序的啟動。init通常不會由使用者程序執行,並且期望程序id為1。如果不是這樣,它將實際執行telinit 8 並將所有引數傳遞給它。init 管理的...

init程序log抓取

adb logcat b events 列印events log資訊 ps顯示瞬間行程 process 的動態 ps az grep i init 查詢init的屬於的程序狀態 android上層都是基於 init程序孵化而來 init程序中的log資訊列印在kernel log 可以通過 adb ...