MOOC-Linux内核lab4 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

本文详细阐述了系统调用的过程,并以C语言库函数time和getpid为例,深入解读了从用户态到内核态的转变机制及关键步骤,包括中断处理、syscall调用、内核函数调用和状态恢复。同时,通过内嵌代码展示了如何在C语言中调用系统调用,确保读者能够理解系统调用在实际编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简述系统调用的过程,以C语言库函数time为例。

首先,调用time c语言api。

第二步, api 通过中断处理,调用syscall,完成从用户态到内核态的转变。期间保存寄存器。

第三步,调用sys_time。

第四步, 切换回用户态,恢复寄存器的值。


如果CS寄存器最低两位是0, 则表示内核态, 如果是3, 则为用户态。

当进行内核态到用户态以及用户态到内核态的转变时,都会修改这个值。


    time_t tt;
    struct tm *t;

    /*tt = time(NULL);*/
    asm volatile(
	    "mov $0, %%ebx\n\t"
	    "mov $0xd, %%eax\n\t"
	    "int $0x80\n\t"
	    "mov %%eax, %0\n\t"
	    : "=m" (tt)
	    );

    t = localtime(&tt);
    printf("%d %d %d %d %d %d\n", t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

这一段内嵌代码调用了13号中断。注意%eax寄存器中存储syscall number,而%ebx中存储变量, 最后把返回值赋值给tt。

这段函数和直接调用time(NULL)是得到相同结果。


下面实现一个getpid()的系统调用。

#include <time.h>
#include <stdio.h>
#include <unistd.h>

void my_sys_getpid()
{
    printf("%s\n", "getpid...");
    long ID;
    asm volatile(
	    "mov $0x14, %%eax\n\t"
	    "int $0x80\n\t"
	    "mov %%eax, %0\n\t"
	    : "=m"(ID)
	    );
    printf("%s %ld\n", "getpid() = ", ID);
}

int main(void)
{
    my_sys_getpid(); /*my syscall*/
    long ID = getpid(); /* C API getpid()*/
    printf("%s %ld\n", "getpid() = ", ID);

    return 0;
}

同样的,在%eax寄存器中存储syscall number,把返回值赋值个给ID。


exit...
getpid() =  16810
getpid() =  16810

通过验证,我的程序是正确的。

原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值