[OS64][025]源码阅读:程序4-11:运行结果,数据结构,第一个进程init_task_union
- 需要结合上文的数据结构,来理解下面的程序执行过程示意图
程序4-11 程序执行过程示意图
- 这个示意图描述与第二个进程 init 相关的完整流程 ,因此有关第一个进程init_task_union的部分代码都省略了,完整代码参见配书代码包程序4-11
- 使用PCB(Process Control Block)程序控制结构体来表示一个进程,进程里面不仅要存执行代码、还要存数据,以及保存相关寄存器的值(即执行现场)
- 作为第二个进程的执行代码的init()函数,功能只是简简单单地输出一条字符串,指明其正在运行,有成功运行过;
- 具体的函数流动顺序是
task_init() -> kernel_thread() -> do_fork() -> switch_to() -> __switch_to() -> kernel_thread_func() -> init() -> do_exit()
task_init()
-
task_init()
函数主要任务是初始化属于第一个进程init_task_union的一些数据结构(init_mm) 以及 调用kernel_thread()
kernel_thread()
- 从这里开始,着手设置与第二个进程
init
相关的各种结构、数据 - 创建并声明了结构体
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
结构体的数据复制到了开辟的内存空间
memcpy(regs,
(void *)((unsigned long)tsk + STACK_SIZE - sizeof(struct pt_regs)),
sizeof(struct pt_regs));
(这之前有使用alloc_pages
分配一个2MB物理页,地址是0x200000起始
,示意图没有体现,这里说明一下)
switch_to()
- 这其实是一个宏
-
pushq %3
的时候,本质上是把kernel_thread_func()
的入口地址压栈了,那么在函数__switch_to()
执行完之后就会跳转到kernel_thread_func()
去执行,此时 - 由于之前有
"D"(prev),"S"(next)
,本质是RDI = 属于第一个进程的task_struct指针 RSI=属于第二个进程的task_struct指针
,刚好构成函数kernel_thread_func()
的两个传入参数
把 init改成helloworld更容易看清楚第二个进程的本质
- 只需要简单地把这两处
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
参考资料
- 函数
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]源码调试:程序4-11 调试过程 objdump bochs: info cpu、print-stack、sreg、breakpoint