[网易云课堂]Linux内核分析(四)—— 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

付何山+原创作品转载请注明出处+《Linux内核分析》MOOC课程;

导读:本文分为三个部分。第一部分将描述实验进程,第二部分将讨论系统调用的工作机制,第三部分将总结实验心得并对第二部分进行简单归纳。

一、课程实验

实验环境:实验楼自带环境
实验步骤:从Linux3.18.6内核中的系统调用表中选择一个作为本次实验所用的系统调用。这里我选择了第20号系统调用。其作用是显示当前进程的进程号。getpid函数的信息可参见此处getpid信息

实验楼中进入实验环境,使用Gvim进行代码编写。具体代码如下:

//getpid.c
#include <stdio.h>
#include <unistd.h>
int main()
{
    pid_t pid = getpid();
    printf("pid is %u\n", (unsigned)pid);

    return 0;
}
//getpid_asm.c
#include <stdio.h>
#include <unistd.h>
int main()
{
    pid_t pid;
    asm volatile(
            "mov $0, %%ebx\n\t"
            "mov $20, %%eax\n\t"
            "int $0x80\n\t"
            "mov %%eax, %0\n\t"
            :"=m"(pid)
    );

    printf("By asm method , the pid is %u\n", (unsigned)pid);
    return 0;
}

使用gcc进行编译即可得到对应的可执行文件,执行后可获得对应的进程号。然而因为每次执行一个可执行文件是随机分配的进程号,两种方式的输出并不相等,为了验证两种方式的输出是相等的,将两者放入同一个文件(对应代码文件getpidtest.c)中执行,得到的结果如下图。

实验结果

所有代码可以在代码库中进行查看。

二、系统调用的工作机制

首先解决系统调用是什么的问题:
系统调用是由内核提供的一系列具备预定功能的多内核函数,而一个或多个系统调用组成API成为应用程序同操作系统之间的接口(当然也可能API并不包含系统调用)。简而言之,就是封装的思想,API也好,系统调用也好,就是一层层的对底层实现的隐藏,从而让程序员能够在不了解底层实现的情况下完成相关的功能。

系统调用的三层封装

上图为系统调用的三层封装,第一层是指Libc中定义的API,这些API封装了系统调用(不一定是一个,有可能是多个,甚至有可能是零个(Ex.完成数学加减运算的API就没有使用系统调用)),在API的实现中使用int 0x80触发一个系统调用中断。

第二层是system_call,它运行于内核态中。system_call是所有系统调用在内核的入口点,在其中的开始处保护用户态程序执行上下文,结束处恢复用户态程序执行上下文,在中间根据传入的系统调用号调用对应的中断服务程序。

第三层是sys_xyz,它是系统调用封装例程:执行具体的系统调用操作,完成用户的系统调用请求;每个系统调用都对应一个封装例程。

整个系统调用的工作过程也如上图所示,调用API,触发系统调用中断,保存上下文,进入中断服务程序,中断服务程序返回,恢复上下文,返回结果

在本实验中,getpid_asm.c的实现即用到了以上所述的方式。内嵌的汇编代码中标明了系统调用号为20,该系统调用的作用是获取当前进程的进程号。而后使用%eax寄存器传递系统调用号,即将调用号20存入寄存器%eax。然后执行系统调用是通过执行int $0x80,底层将执行如上所说的工作过程。结果将存储在%eax寄存器中,写入预先定义的变量pid中。

三、总结

系统调用是程序员使用相关底层功能的桥梁,使程序员能够摆脱底层的复杂性。其具体的执行方式就是通过中断。通过本实验,更加熟悉了系统调用的本质,以及系统调用和中断的关联。这个过程大致如下所示:

应用程序调用API函数,该函数将对应的系统调用号及参数保存,触发软中断,然后陷入内核态,system_call根据系统调用号调用对应的内核函数,内核函数执行完毕后将结果存放在eax中并返回给程序,而后返回应用程序所在的状态。

总体来说本次实验还是比较简单的,毕竟是我们编程时常常会用到的东西。希望继续努力,持续进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值