《Linux内核分析》(四)Linux内核的系统调用(上)

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

一、实验过程:

选择一个系统调用(13号系统调用time除外),系统调用列表参见 http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/syscall_32.tbl

使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用,在实验楼Linux虚拟机环境下完成实验。

 二、实验分析:

实验截图如下:

 

实验代码:

getpid.c:

#include<stdio.h>
#include<unistd.h>
int main(void)
{
    printf("Process id:%d\n",getpid());
    return 0;
}

getpid-asm.c:

 

#include<stdio.h>
#include<unistd.h>
int main(void)
{
    int pid;
    asm volatile(
        "mov $0,%%ebx\n\t" //把"基地址"(base)寄存器ebx置零。
        "mov $0x14,%%eax\n\t"//eax用于传递系统调用号和储存系统调用返回值
        "int $0x80\n\t"    //执行系统调用
        "mov %%eax,%0\n\t"   //把eax的值赋值给pid
        : "=m"(pid)   
    );
    printf("Process id:%d\n",pid);
    return 0;
}

 

  

  系统调用是操作系统所提供的用于用户态进程和硬件设备之间进行交互的接口,这样用户不用去了解复杂的底层的硬件编程,也使系统的安全性大大提高了,同时用户程序也会具有可移植性。系统调用是通过软中断来向内核发出一个明确的请求的。

  系统调用的过程为:API引用封装例程,封装例程触发一个中断,其中的中断向量对应系统调用处理程序的入口,再执行系统调用处理程序中的中断服务程序,中断服务程序结束后再返回用户态。

   下面以图示来说明系统调用的过程:xyz()即系统调用对应的API,这个API封装了一个系统调用,触发一个中断,int 0x80中断向量对应了内核代码system_call的入口。system_call中有很多中断服务程序,如sys_xyz(),执行完中断服务程序,会执行ret_from_sys_call,此时可能会有进程调度,如果没有进程调度,则执行iret返回到用户态。

    

 

    内核中有很多不同的系统调用,进程必须指明需要哪个系统调用,这需要传递一个参数,叫做系统调用号,此参数使用eax寄存器来传递。系统调用有一个返回值,此返回值使用eax来存储。

   三、总结:

  系统调用有“三层皮”:第一层皮即API(如上图中的xyz()函数),第二层皮为系统调用处理程序(如上图中的system_call),第三层皮为系统调用服务例程(即sys_xyz())。通过这三层皮,完成了系统调用的整个过程。

posted on 2015-03-29 21:41  xyon  阅读(173)  评论(0)    收藏  举报