【举例】上周我的blog中自选的系统调用服务恰好是fork,代码如下:
#include #include int main ()
{
pid_t fpid;
fpid = fork();
if (fpid < 0)
printf("error in fork!");
elseif (fpid == 0) {
printf("i am the child process, my process id is %d
",getpid());
}
else {
printf("i am the parent process, my process id is %d
",getpid());
}
return0;
}
对于父进程来说:
通过系统调用fork()陷入内核。完成系统调用2号服务例程后,从iret返回,并恢复之前SAVE_ALL的寄存器值,从内核态回到用户态,继续执行用户态代码 printf("i am the parent process, my process id is %d
",getpid()),所以打印的是子进程pid值。
对于子进程来说:
由于是父进程创建的,一出生就存在于内核中了。用户代码fork()之前的它管不了,只能管fork()之后的代码。于是ret_from_fork–>syscall_exit,恢复父进程保存在SAVE_ALL的寄存器值,从内核态回到用户态,继续执行用户态代码printf("i am the child process, my process id is %d
",getpid())。由于ax寄存器值赋值为0,所以返回值为0,打印的是0。
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
gdb
file linux-3.18.6/vmlinux
target remote:1234
// 设置断点
b sys_clone # 因为fork实际上是执行的clone
b do_fork
b dup_task_struct
b copy_process
b copy_thread
b ret_from_fork
c
n
……