[OS64][025]源碼閱讀:程序4-11:運行結(jié)果眨唬,數(shù)據(jù)結(jié)構(gòu)卸例,第一個進程init_task_union
- 需要結(jié)合上文的數(shù)據(jù)結(jié)構(gòu),來理解下面的程序執(zhí)行過程示意圖
程序4-11 程序執(zhí)行過程示意圖
- 這個示意圖描述與第二個進程 init 相關(guān)的完整流程 始苇,因此有關(guān)第一個進程init_task_union的部分代碼都省略了砌烁,完整代碼參見配書代碼包程序4-11
- 使用PCB(Process Control Block)程序控制結(jié)構(gòu)體來表示一個進程,進程里面不僅要存執(zhí)行代碼催式、還要存數(shù)據(jù)函喉,以及保存相關(guān)寄存器的值(即執(zhí)行現(xiàn)場)
- 作為第二個進程的執(zhí)行代碼的init()函數(shù),功能只是簡簡單單地輸出一條字符串荣月,指明其正在運行管呵,有成功運行過;
- 具體的函數(shù)流動順序是
task_init() -> kernel_thread() -> do_fork() -> switch_to() -> __switch_to() -> kernel_thread_func() -> init() -> do_exit()
task_init()
-
task_init()
函數(shù)主要任務(wù)是初始化屬于第一個進程init_task_union的一些數(shù)據(jù)結(jié)構(gòu)(init_mm) 以及 調(diào)用kernel_thread()
kernel_thread()
- 從這里開始哺窄,著手設(shè)置與第二個進程
init
相關(guān)的各種結(jié)構(gòu)捐下、數(shù)據(jù) - 創(chuàng)建并聲明了結(jié)構(gòu)體
regs
,也是在這里 填入了init
的入口地址以及kernel_thread_func()
的入口地址
struct pt_regs regs;
memset(®s,0,sizeof(regs));
struct pt_regs
{
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long rbx;
unsigned long rcx;
unsigned long rdx;
unsigned long rsi;
unsigned long rdi;
unsigned long rbp;
unsigned long ds;
unsigned long es;
unsigned long rax;
unsigned long func;
unsigned long errcode;
unsigned long rip;
unsigned long cs;
unsigned long rflags;
unsigned long rsp;
unsigned long ss;
};
do_fork()
- 把上面的那個
regs
結(jié)構(gòu)體的數(shù)據(jù)復(fù)制到了開辟的內(nèi)存空間
memcpy(regs,
(void *)((unsigned long)tsk + STACK_SIZE - sizeof(struct pt_regs)),
sizeof(struct pt_regs));
(這之前有使用alloc_pages
分配一個2MB物理頁堂氯,地址是0x200000起始
蔑担,示意圖沒有體現(xiàn),這里說明一下)
switch_to()
- 這其實是一個宏
-
pushq %3
的時候咽白,本質(zhì)上是把kernel_thread_func()
的入口地址壓棧了啤握,那么在函數(shù)__switch_to()
執(zhí)行完之后就會跳轉(zhuǎn)到kernel_thread_func()
去執(zhí)行,此時 - 由于之前有
"D"(prev),"S"(next)
晶框,本質(zhì)是RDI = 屬于第一個進程的task_struct指針 RSI=屬于第二個進程的task_struct指針
排抬,剛好構(gòu)成函數(shù)kernel_thread_func()
的兩個傳入?yún)?shù)
把 init改成helloworld更容易看清楚第二個進程的本質(zhì)
- 只需要簡單地把這兩處
init
修改成helloworld
,其余代碼不變
unsigned long helloworld(unsigned long arg)
{
color_printk(YELLOW,BLACK,"hello world is running,arg:%#018lx\n",arg);
return 1;
}
void task_init()
{
kernel_thread(helloworld,10,CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
}
- 重新編譯授段、連接蹲蒲、運行可以得到hello world
參考資料
- 函數(shù)
int foo(a, b, c, d, e, f, g ...)
匯編視角
RDI = a
RSI = b
RDX = c
RCX =d
R8 = e
R9 = f
其余通過 memory 傳遞
RAX = 返回值
- [OS64][027]源碼調(diào)試:程序4-11 調(diào)試過程 objdump bochs: info cpu届搁、print-stack、sreg、breakpoint