2020-2021-1 20209327 《Linux内核原理与分析》第五周作业
系统调用的两种使用方式
实验准备
首先,在/LinuxKernel/linux-3.18.6/arch/x86/syscalls目录下查看syscall_32.tbl文件,获取系统调用号信息。选择getuid进行此次实验,其系统调用号为24,即0x18:

通过man getuid查看getuid系统调用相关信息,可以看到getuid的功能是返回当前调用进程的真实用户ID:

对getuid的功能及其头文件等信息有了一定了解之后,开始进行正式的实验过程。
使用库函数API的方式利用系统调用
编写getuid.c文件,通过getuid()获取用户ID信息:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
int usr;
usr=getuid();
printf("The user id is %d\n",usr);
return 0;
}

编译并执行,结果如下:

在C代码中嵌入汇编使用系统调用
修改getuid.c文件,嵌入汇编代码。将系统调用号0x18赋给eax寄存器,执行系统调用后将返回值赋给变量usr:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
int usr;
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x18,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(usr)
);
printf("The user id is %d\n",usr);
return 0;
}

编译并执行,结果与前一种方法相同:

实验总结
系统调用的三层皮:API XYZ,中断向量system_call,中断服务程序sys_xyz。系统调用号将xyz和sys_xyz关联起来。
系统调用工作机制:Linux下的系统调用是通过int 0x80实现的,每个系统调用都有相应的系统调用号作为唯一的标识,通过系统调用号进入相应的系统调用,使用软中断进入内核态。中断发生后会保护现场,将用户的当前栈顶地址,当时的状态字和cs:eip的值进行压栈。之后进入由用户态切换到内核态,处理完中断程序后还原现场,返回用户态。
浙公网安备 33010602011771号