初始化0號程序

2021-05-24 00:56:51 字數 4249 閱讀 7273

arch/x86/kernel/head_32.s

的336

行,進入分頁後的核心**段,執行

lss stack_start,%esp

指令,立即為程序

0建立核心態堆疊。

stack_start

定義在657

行:657 entry(stack_start)

658 .long init_thread_union+thread_size

659 .long __boot_ds

我們看到核心態堆疊由

init_thread_union

表示,其在

include/linux/sched.h

中被定義成乙個全域性變數:

extern union thread_union init_thread_union;

union thread_union ;

#define thread_size (page_size << thread_order)

由於page_size

是4096

,thread_order在32

位x86

體系中是

1,所以

thread_size

的值為8k

。所以這個

thread_union

的大小也為

8k。關於核心棧的詳細內容請參考部落格「程序相關的資料結構」

.那麼,對於乙個程序,最重要的是什麼呢?兩個東西,乙個是

thread_info

,另乙個就是著名的

task_struct

。這個0

號程序的

thread_info

,我們已經看到了,是在

init_thread_union

中。那麼這個

task_struct

又在哪兒呢?看到

arch/x86/kernel/init_task.c

:23 union thread_union init_thread_union __init_task_data =

24;

扎眼一看,很奇怪,怎麼多了個

__init_task_data

?別緊張,其實,它只是乙個巨集,不是什麼變了,來自

include/linux/init_task.h

的186

行:#define __init_task_data __attribute__((__section__(".data.init_task")))

那麼,上面的內容就展開成了:

union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) =

;這是一條賦值語句,對聯合體

init_thread_union

賦初始值。暈了吧,

c語言的功底是多麼重要啊,通過核心的學習,你也學會了如何對聯合體賦初值並且把資料放進指定的資料段

.data.init_task

了吧。繼續,具體到如何賦值呢?先講講

init_task

這個全域性變數,定義在

arch/x86/kernel/init_task.c

的第31

行:struct task_struct init_task = init_task(init_task);

這不,0

號程序的

task_struct

出現了,就是

init_task

。在對init_thread_union

賦初值的時候,同時也通過呼叫

init_task

巨集對init_task

賦初值:

110#define init_task(tsk)/

111,/

127.rt

= ,/

132.tasks= list_head_init(tsk.tasks),/

133.pushable_tasks = plist_node_init(tsk.pushable_tasks, max_prio), /

134.ptraced= list_head_init(tsk.ptraced),/

135.ptrace_entry= list_head_init(tsk.ptrace_entry),/

136.real_parent= &tsk,/

137 .parent= &tsk,/

138.children= list_head_init(tsk.children),/

139.sibling= list_head_init(tsk.sibling),/

140.group_leader

= &tsk,/

141.real_cred= &init_cred,/

142.cred= &init_cred,/

143.cred_guard_mutex =

/ 144__mutex_initializer(tsk.cred_guard_mutex),/

146.thread= init_thread,

/ 147.fs= &init_fs,/

148.files= &init_files,/

149.signal= &init_signals,/

150.sighand= &init_sighand,/

151.nsproxy= &init_nsproxy,/

152.pending= }},/

155.blocked= },/

156.alloc_lock= __spin_lock_unlocked(tsk.alloc_lock),/

157.journal_info= null,/

158.cpu_timers= init_cpu_timers(tsk.cpu_timers),/

159.fs_excl= atomic_init(0),/

160.pi_lock= __raw_spin_lock_unlocked(tsk.pi_lock),/

161.timer_slack_ns = 50000, /* 50 usec default slack *//

162.pids = ,

/ 167.dirties = init_prop_local_single(dirties),/

168init_ids/

169init_perf_events(tsk)

/ 170

init_trace_irqflags/

171init_lockdep/

172init_ftrace_graph/

173init_trace_recursion/

174init_task_rcu_preempt(tsk)/

175}

至於task_struct

的詳細介紹,請檢視部落格「程序相關的資料結構」,這裡只挑幾個重要的來說說。

0號程序的

stack

就是剛才

init_thread_info

的位址;

parent

是他自己;

thread

是init_thread

。還有一些是常量,如

init_fs

。等我們用到了再回過來看它。

現在,0

號程序task_struct

有了,下面就該來講講

init_thread_info

巨集了,在

arch/x86/include/asm/thread_info.h

:46#define init_thread_info(tsk)/

47,/

57}

執行完這個巨集以後,

init_thread_union

就被初始化成以上內容了,至此,

0號程序的

task_struct

和thread_info

就初始化完畢了。注意,這個初始化不是在

head_32.s

中初始化的。大家也看到了,上面的內容都是在編譯的時候作為乙個資料全域性資料被初始化的,並且把他們放在

.data.init_task

資料段中。

head_32.s

中只是將

esp指標指向這個已經被初始化了的

init_thread_union

以上8k

作為棧頂,並向下移動(回憶一下

c程式的特點,並參考「程序相關的資料結構

」中那個圖)。

systemd初始化程序

systemd初始化程序 1 linux的開機啟動 linux作業系統開機過程我們可以簡單的理解為這幾個步驟 即從bios介面開始,然後進入bootloader,在載入系統核心,然後核心進行初始化,最後啟動初始化程序。同時,初始化程序是linux系統的第乙個程序。systemd 儘管開機速度得到了提...

linux中0號任務的建立以及堆疊初始化

開啟linux系統的命令列,敲下 ps a 命令,就能看到系統中的所有任務 其中有乙個pid號為0任務格外的顯眼。我們知道linux中的task都是通過fork族函式由父程序創造出來,而這個0號程序卻是個例外,它由人類捏造出來,沒有parent。linux中所有task都由乙個task struct...

陣列,結構體初始化 0

一直以為 int a 256 是把a的所有元素初始化為0,int a 256 是把a所有的元素初始化為1.除錯的時檢視記憶體發現不是那麼一回事,翻了一下 the c programming language 總算有定論。pdf的竟然不然複製,就把它這章翻譯了,如下 5.2.1 陣列初始化 陣列可以用...