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

实验过程

查看系统调用号


这里使用的是getpid函数与mkdir函数,对应的系统调用号为20与39.

实现系统调用

getpid函数
#include<stdio.h>
#include<unistd.h>
int main()
{       
      int pid;
      pid=getpid();
      printf("the pid is %d",pid);
      return 0;  
}


使用汇编代码实现:

#include<stdio.h>
#include<unistd.h>
int main()
{
      int pid;
      asm volatile(
            "mov $0x14,%%eax
	"
            "int $0x80
	"
            "mov %%eax,%0
	"
            :"=m"(pid));
      printf("the pid is %d
",pid);
      return 0;
}


汇编代码细化了调用过程,getpid函数没有参数,首先将对应的系统调用号传入到ax寄存器中,int指令使系统内陷,执行相应的系统调用,最后返回值存入ax寄存器中,将ax中的返回值取出放入变量pid,打印输出。

mkdir函数
#include<stdio.h>
#include<unistd.h>
int main(){
      int ret;
      char *dir="dir";
      asm volatile(
            "movl %1,%%ebx
	"
            "movl $0x27,%%eax
	"
            "int $0x80"
            :"=a"(ret)
            :"b"(dir));
      printf("the ret is %d
",ret);
      return 0;
}


与上面的getpid函数相比,mkdir函数对应多了一个参数,其需要传入一个字符数组,这里以一个指针的形式传入到寄存器bx中,其他的操作与getpid函数无异。

小结

系统调用的三层皮:API、中断向量对应的system_call、中断服务程序sys_xyz
API:应用程序接口是一个函数定义,系统调用通过软中断向内核发出一个明确的请求。
系统调用:操作系统为用户态进程与硬件设备进行交互提供了一组接口。
当API中包含系统调用时,通过系统调用号进入相应的系统调用,然后使用软中断进入内核态。中断发生后会保护现场,将用户的当前栈顶地址,当时的状态字和cs:eip的值进行压栈。之后进入由用户态切换到内核态,处理完中断程序后还原现场,返回用户态。
xyz()函数,是系统调用对应的API,这个应用程序编程接口里面封装了一个系统调用,这个系统调用会触发一个int 0x80的中断,0x80这个中断向量对应着system_call这个内核代码的起点,这个内核代码里面会有SAVE_ALL,然后执行到sys_xyz()中断服务程序,进入程序里面处理,在中断服务程序执行完之后会ret_from_sys_call,在return的过程中可能会发生进程调度(这是一个进程调度的时机),如果没有进程调度,就会iret,回到用户态接着执行。

原文地址:https://www.cnblogs.com/yanzs/p/13945080.html