2019-2020-1 20209329《Linux内核原理与分析》第五周作业

系统调用的两种方式

一、库函数API调用

以系统函数rename为例,研究Linux系统的系统调用过程。
编写一个简单的API调用系统函数rename的c程序

#include <stdio.h>
int main(){
      int ret;
      char *oldname = "hello.c";
      char *newname = "20209329_zbl";
      ret = rename(oldname, newname);
      if(ret == 0)      //rename函数调用成功将返回0
            printf("Renamed successfully\n");
      else
            printf("Unable to rename the file\n");
      return 0;
}

编译运行,可见该程序已经将当前目录下的hello.c重命名为20209329_zbl。
接下来,通过c语言内嵌汇编的方式,深入了解系统函数的调用过程。

二、内嵌汇编调用
编写一个内嵌汇编的c语言程序,同样实现系统函数rename的调用。

#include <stdio.h>
int main(){
      int ret;
      char *oldname = "hello.c";
      char *newname = "20209329_zbl";
      asm volatile(
                        "movl %2,%%ecx\n\t" //参数按顺序赋值给ebx,ecx
                        "movl %1,%%ebx\n\t"
                        "movl $0x26,%%eax\n\t"//实现将系统调用号38传递给eax
                        "int $0x80"          //触发系统调用
                        :"=a"(ret)
                        :"b"(oldname), "c"(newname)
                                                      );
      if(ret == 0)
            printf("Renamed successfully\n");
      else
            printf("Unable to rename the file\n");
      return 0;
}

注意在编译的时候要指定 -m32,另外将文件名还原为hello.c,执行程序。

可见,通过内嵌汇编实现了与API调用同样的功能。

三、总结

以rename函数为例,系统调用的三层机制分别为rename(),system_call(通过int $0x80触发系统调用),sys_rename(通过系统调用号38指定系统调用)。
系统函数的调用过程:从API函数,进入系统调用的封装,封装里的int指令会触发软中断,保存用户态的上下文,0x80对应中断服务程序的入口,通过系统调用号指定系统调用例程,执行例程,例程执行完毕后返回用户态。

posted @ 2020-11-06 22:49  不冷惊喜  阅读(107)  评论(0编辑  收藏  举报