分析system_call中断处理过程
潘俊洋
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、实验情况 选择了2号调用fork调用来做实验:
1、用实验楼的虚拟机打开shell
cd LinuxKernel
rm menu -rf
git clone https://github.com/mengning/menu.git
cd menu
make rootfs
运行结果见截图
2、在test.c中增加2个函数代码 vi test.c
int menufork(int argc, char *argv[])
{
pid_t fpid;
int count = 0;
fpid = fork();
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0) {
printf("i am the child process, my process id is %d\n",getpid());
count++;
}
else {
printf("i am the parent process, my process id is %d\n",getpid());
count++;
}
printf("count: %d\n",count);
return 0;
}
int menuforkAsm(int argc, char *argv[])
{
pid_t fpid;
int count = 0;
asm volatile (
"mov $0, %%ebx\n\t"
"mov $0x2, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=m" (fpid)
);
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0) {
printf("i am the child process, my process id is %d\n",getpid());
count++;
}
else {
printf("i am the parent process, my process id is %d\n",getpid());
count++;
}
printf("count: %d\n",count);
return 0;
}
int main()
{
PrintMenuOS();
SetPrompt("MenuOS>>");
MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
MenuConfig("quit","Quit from MenuOS",Quit);
MenuConfig("time","Show System Time",Time);
MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
/* add for menufork */
MenuConfig("menufork","menufork --fork a proc", menufork);
MenuConfig("menufork-asm","menufork-asm --fork a proc(asm)",menuforkAsm);
ExecuteMenu();
}
3、重新编译,运行2个新命令menufork, menufork-asm
在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中, fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。 引用一位网友的话来解释fpid的值为什么在父子进程中不同。“其实就相当于链表,进程形成了链表,父进程的fpid(p 意味point)指向子进程的进程id, 因为子进程没有子进程,所以其fpid为0.
4、用gdb调试代码
gdb
file linux-3.18.6/vmlinux 加载调试用的符号表
target remote:1234
b start_kernel 设置断点
c
b sys_fork
二、代码分析
/linux-3.18.6/arch/x86/kernel/entry_32.S
489 # system call handler stub
490ENTRY(system_call)
491 RING0_INT_FRAME # can't unwind into user space anyway
492 ASM_CLAC
493 pushl_cfi %eax # save orig_eax
494 SAVE_ALL
495 GET_THREAD_INFO(%ebp)
496 # system call tracing in operation / emulation
497 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
498 jnz syscall_trace_entry
499 cmpl $(NR_syscalls), %eax
500 jae syscall_badsys
501syscall_call:
502 call *sys_call_table(,%eax,4)
503syscall_after_call:
504 movl %eax,PT_EAX(%esp) # store the return value
505syscall_exit:
三、简单总结 通过使用库函数API和C代码中嵌入汇编代码两种方式为menuos增加2种fork系统调用命令,基本熟悉了系统调用的过程。