• Linux内核设计第四周学习总结 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用


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

    实验目的:

    使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用,理解系统调用的工作机制。

    实验过程:

    本文实验使用亚马逊云计算平台(AWS)Ubuntu 14.04.2 LTS 64bit


     

    本文实验选择24号和47号系统调用,分别获取当前用户uid(用户ID)和gid(组ID),即模拟Linux系统“id”命令。


     

    编写两段代码,分别使用库函数API和C代码中嵌入汇编代码,源码如下:

    uidgid.c(使用库函数API方式):


     

    程序中通过调用getuid()和getgid()函数来获取当前执行用户uid和gid

    uidgid_asm.c(使用C代码中嵌入汇编代码方式):


     

    内嵌汇编代码版本源码中将原来两行通过API函数获取uid和gid的代码注释掉,用汇编代码替换。

    首先将ebx寄存器清零,表示无参数传入。

    然后分别将0x18和0x2f(十进制24和47)赋值给eax寄存器,表示需要调用的系统调用号,24为getuid,47为getgid。

    执行int 0x80来执行系统调用。

    之后eax寄存器保存了返回值,将它分别赋值给输出uid或gid变量。

    完成整个汇编代码的系统调用。

    分别编译两个源码文件:


     

    分别执行系统id命令以及两个编译好的程序:


     

    上面的截图分别表示普通用户ubuntu和管理员用户root分别执行系统自带命令id,库函数API方式uidgid,内嵌汇编方式uidgid_asm这三种方式运行得到的结果是一样的。

    实验分析:

    通过实验执行结果可知,程序成功完成了系统调用获取当前用户uid和gid的操作,通过内嵌汇编代码可以清晰的看出调用系统调用的工作过程。

    首先将ebx寄存器清零,表示无参数传入。

    然后分别将0x18和0x2f(十进制24和47)赋值给eax寄存器,表示需要调用的系统调用号,24为getuid,47为getgid。

    执行int 0x80来执行系统调用。

    之后eax寄存器保存了返回值,将它分别赋值给输出uid或gid变量。

    完成整个汇编代码的系统调用。

    在Linux系统中是通过激活0x80中断来触发系统调用的,需要调用的系统调用号实现赋值给eax存储器,如果有传入参数可赋值给ebx寄存器,如果多于1个则按顺序赋值给ebx、ecx、edx、esi、edi、ebp,如果超过6个则通过指针变量指向另一片堆栈区,如果无参数传入则赋值为0。

    实验总结:

    虽然Intel X86 CPU有4种执行级别0~3,但是在Linux系统中仅使用了0和3级,分别表示内核态用户态

    一些涉及底层、硬件、核心的操作必须在内核态下才允许执行,为操作系统程序和驱动程序专享,普通程序仅能执行在用户态下。如果普通程序需要涉及内核态的操作,就需要通过系统调用来实现。这样做的好处是屏蔽平台相关操作降低了软件开发难度,增强了系统安全性,使程序具有更好的移植性(Linux系统及其他Unix系统遵循统一标准,系统调用基本一样)。

  • 相关阅读:
    as3工程和flex工程的区别
    Timer的repeatCount和currentCount的区别
    mouseChildren为false后,
    flex编译时,会把trace语句也编译进去
    stage和root的区别
    flex编译时,会把trace语句也编译进去
    水瓶座(1.202.19)更多星座运程
    如何更改titleWindow组件上的title字体大小?
    转贴关于AsWing和MXML 选项
    Eclipse中的文本编辑器使用技巧
  • 原文地址:https://www.cnblogs.com/20135310cqr/p/5282979.html
Copyright © 2020-2023  润新知