《Linux内核分析》 第五节 扒开系统调用的三层皮(下)

摘要:范闻泽

原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

 

 

1.实验环境是使用本课程配置的实验楼虚拟机环境,打开命令行客户端,cd LinuxKernel目录,使用命令rm -rf menu 删除原来的代码,使用git clone https://github.com/mengning/menu.git获取menu的最新代码,然后cd menu进入menu子文件夹,使用vi test.c打开文件,将上周实验的代码拷贝入test.c中,构造成两个函数,成为menu的两个菜单项。

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;

}

在main()函数中添加两行命令

输入两个函数(输错了好几次)


3、运行2个新函数menufork, menufork-asm

函数编译完成后,意味着出现了两个进程,父进程和子进程,而两个进程返回的结果是不同的,子进程返回的函数值是0,父进程返回的是子进程的ID,所以可以通过函数值来判断是子进程还是父进程。

 

4、用gdb调试代码

gdb
file linux-3.18.6/vmlinux    加载调试用的符号表
target remote:1234
b start_kernel  设置断点
c
b sys_fork

在sys_getpid上打上断点。

最后无法继续跟踪调试代码,system_call()不是普通的函数,gdb不能在此停下。


5、简单总结

这次实验比较容易理解,但操作起来有点麻烦,在输入代码时还出现了几次错误导致时间大大增加,好在完成了。回顾整个实验,系统在进入内核态的同时先保护了中断地址和环境,然后调用系统函数,通过中断向量表将每一个系统调用和相关的函数关联起来,执行完系统函数,恢复中断环境,继续执行程序。

 

posted on 2016-03-27 18:34  fwz  阅读(207)  评论(0编辑  收藏  举报