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的值进行压栈。之后进入由用户态切换到内核态,处理完中断程序后还原现场,返回用户态。

posted @ 2020-11-06 14:38  20209327  阅读(153)  评论(0编辑  收藏  举报