Linux内核分析— —扒开系统调用的三层皮(上)

实验部分

  • 根据系统调用表,选取一个系统调用。我选得是mkdir这个系统调用,其系统调用号为39,即0x27

  • 由于mkdir函数的原型为
    int mkdir (const char *filename, mode_t mode)

    所以根据其原型编写一下代码:

    #include <stdio.h>

    #include <sys/types.h>

    #include <sys/stat.h>

    int main()

    {

    const  char *ch = "test"; //创建的文件夹名称

    mode_t mode = 0700;        //创建的文件夹的权限

    int flag = 0;        //是否创建成功新的文件夹的标识符

    flag = mkdir(ch,mode);    //调用mkdir

    if(flag==0)                //flag=0则创建成功,否则失败

    {

    printf("succeed");

    }

    else

    printf("error");

    return 0;

    }

  • mkdir.c的运行结果如下:

Linux内核分析— —扒开系统调用的三层皮(上)

  • 当运行完mkdir可执行文件时,产生了新的文件夹test。

  • 改编成会变代码调用

    #include <stdio.h>

    #include <sys/types.h>

    #include <sys/stat.h>

    int main()

    {

    char *ch="test-asm"; //创建文件夹的名称

    mode_t mode=S_IRWXU;  //创建新的文件夹的权限

    int flag=0;            //标识符

    asm volatile(

    "mov $0x27,%%eax\n\t"    //系统调用号赋给eax寄存器

    "mov %1,%%ebx\n\t"        //将文件夹的名称赋给ebx寄存器

    "mov %2,%%ecx\n\t"        //将文件夹的权限赋给ecx寄存器

    "int $0x80\n\t"            //开启中断,执行mkdir系统调用

    "mov %%eax,%0\n\t"        //将返回值赋给flag

    :"=m"(flag)                //输出变量flag

    :"d"(ch),"D"(mode)        //输入变量ch与mode

    );

    if(flag==0)            //flag=0则创建成功,否则失败

    printf("succeed");

    else

    printf("error");

    return 0;

    }

  • 结果如下图:

Linux内核分析— —扒开系统调用的三层皮(上)

总结

1.系统调用的三层皮:xyz    system_call    sys_xyz

对应的是API,中断向量对应的中断服务程序,系统调用服务程序。

API:应用编程接口

它与系统调用的关系:API可能直接提供用户态的服务,不是一个API都有与之相对应的系统调用。

2.中断处理,用户态及内核态

通过cs:eip的值判断代码段是在用户态还是内核态

中断处理是一种由用户态进入内核态的方式(系统调用也可以理解为是一种中断)

中断发生后,首先要保存现场

3.系统调用简单点说,就是通过设置输入输出变量,令其存在于ebx等寄存器中,而后将系统调用号赋给eax寄存器,最后通过int 0x80来进行中断,从而开始所选择的系统调用。

若有返回值,则将返回值传至eax寄存器中,我们便可以利用返回值来给出一定的结论(如操作成功或失败)。

注:

姓名:林涵锦

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

上一篇:CSS3和H5的新特性


下一篇:java生成解析xml的另外两种方法Xstream