分析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系统调用命令,基本熟悉了系统调用的过程。

 

posted on 2016-03-27 13:25  20135230潘俊洋  阅读(183)  评论(0编辑  收藏  举报