码迷,mamicode.com
首页 > 其他好文 > 详细

从内核看系统调用

时间:2015-04-05 20:21:50      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

本周学习了孟宁老师的《Linux内核分析》,按照课程要求,做实验如下:

 

首先使用gdb跟踪一个系统调用,我们选择上周实验所写的代码,修改这两段代码成两个系统调用,放入根文件系统中,作为本次实验将要观察的系统调用。

修改代码如下:

1) c实现的系统调用

int mkdir_c(int argc, char **argv)
{
    if(argc != 2)
        printf("Illegal parameter!!\n");

    if(mkdir(argv[1]) == -1)
    {
        printf("Mkdir error!!\n");
        return -1;
    }

printf("Mkdir success!!\n");
return 0; }

2) 使用汇编语言实现的系统调用

int mkdir_asm(int argc, char **argv)
{
    if(argc != 2)
        printf("Illagel parameters!!\n");

    int ret = 0;
    asm volatile(
            "mov $0, %%eax\n\t"
            "mov $0x27, %%eax\n\t"
            "int $0x80\n\t"
            "mov %%eax, %0\n\t"
            :"=m"(ret)
            :"b"(argv[1])
            );

    if(ret == -1)
    {
        printf("Mkdir Error!!\n");
        return -1;
    }

printf("Mkdir success!!\n");
return 0; }

 

打开实验楼环境,进入menu目录下

cd /home/shiyanlou/LinuxKernel/menu

打开test.c文件,假如上面两段代码,如图所示:

技术分享

技术分享

在main函数中添加两行代码注册这两个系统调用:

技术分享

重新编译,制作成根文件系统镜像。使用qemu仿真环境加载内核和根文件系统,启动系统。为了方便,我们使用把这一系列命令都写入Makefile文件中,所以只需在终端执行如下命令:

make rootfs

就能完成全部动作:

技术分享

技术分享

我们可以执行我们所添加的命令了。

 

接下来我们使用gdb工具来对系统调用进行调试。

首先使用qemu进入调试模式,冻结住内核:

技术分享

启动gdb,加载调试符号表,开始进行调试:

技术分享

在system_call函数处设置了断点,但是无法在此处停止,因为system_call函数所在的entry_32.s文件是汇编代码,gdb对汇编代码的调试能力有限。

 

为了了解系统调用机制的处理过程,我们对system_call这段代码进行阅读和分析:

具体的代码参见:http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/kernel/entry_32.S

首先内核要初始化系统调用机制,我们知道start_kernel是内核的入口地址,在这个函数中系统完成一系列的初始化工作,所以系统调用机制的初始化工作也必定在这个函数中,其中的trap_init函数就是负责对系统调用机制进行初始化,

// in init/main.c   start_kernel
553
/* 554 * These use large bootmem allocations and must precede 555 * kmem_cache_init() 556 */ 557 setup_log_buf(0); 558 pidhash_init(); 559 vfs_caches_init_early(); 560 sort_main_extable(); 561 trap_init(); 562 mm_init();

我们进入trap_init函数:

837
838#ifdef CONFIG_X86_32
839    set_system_trap_gate(SYSCALL_VECTOR, &system_call);
840    set_bit(SYSCALL_VECTOR, used_vectors);
841#endif
842

这一段代码把中断向量表中的0x80号中断指向system_call代码段处,我们进入SYSCALL_VECTOR可以看到这个宏代表的就是0x80:

50#ifdef CONFIG_X86_32
51# define SYSCALL_VECTOR            0x80
52#endif
53

接下来我们还分析system_call这段代码:

489    # system call handler stub
490    ENTRY(system_call)
491    RING0_INT_FRAME            # cant 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:
506    LOCKDEP_SYS_EXIT
507    DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we dont miss an interrupt
508                    # setting need_resched or sigpending
509                    # between sampling and the iret
510    TRACE_IRQS_OFF
511    movl TI_flags(%ebp), %ecx
512    testl $_TIF_ALLWORK_MASK, %ecx    # current->work    //检测当前的任务
513    jne syscall_exit_work    //是否跳到syscall_exit_work来处理
514
515restore_all:
516    TRACE_IRQS_IRET

我们来看syscall_exit_work这段代码:

        # perform syscall exit tracing
655    ALIGN
656    syscall_exit_work:
657    testl $_TIF_WORK_SYSCALL_EXIT, %ecx
658    jz work_pending    //跳转至信号处理,work_reached进程调度处理等
659    TRACE_IRQS_ON
660    ENABLE_INTERRUPTS(CLBR_ANY)    # could let syscall_trace_leave() call
661                    # schedule() instead
662    movl %esp, %eax
663    call syscall_trace_leave
664    jmp resume_userspace
665END(syscall_exit_work)

最后我们绘制流程图来表述从system_call到iret这一段代码的执行流程:

技术分享

 

以上便是我对本次试验的全部理解,如有错误,还望指正。

 

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

从内核看系统调用

标签:

原文地址:http://www.cnblogs.com/slz-coder150315/p/4394324.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!