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 陣列初始化 陣列可以用...