第四章 系统调用的三层机制(上)

知识点总结:

  • 系统调用:系统调用是操作系统为用户态进程与硬件设备进行交互提供的一组接口。
  • 系统调用的功能特性:
    • 把用户从底层的硬件编程中解放出来;
    • 极大地提高了系统的安全性;
    • 使用户程序具有可移植性。
  • API:应用编程接口(application program interface)
    • 一个API可能只对应一个系统调用,也可能内部由多个系统调用实现;
    • 一个系统调用也可能被多个API调用;
    • 不涉及与内核进行交互的API内部不会封装系统调用,如求绝对值的数学函数abs()。
  • 系统调用三层机制
    • API
    • 中断向量对应的system_call。(system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即由eax传递的系统调用号
    • 系统调用内核处理函数sys_xyz()
  • 什么是用户态和内核态:
    • 用户态:(低级别指令)对于32位的4GB进程地址空间,只能访问0x00000000~0xbfffffff的地址空间。
    • 内核态:(高指令执行级别)在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这时CPU执行级别就对应着内核态。CS:EIP的值可以是任意地址。
  • 用户态进入内核态的主要方式:中断处理
  • 中断/int指令发生后第一件事就是保护现场,中断处理结束前最后一件事是恢复现场。
  • 系统调用的参数传递
    • 无法通过参数压栈的方式,而是通过比较特殊的寄存器传递参数的方式。
    • 寄存器传递参数具有如下限制:
      • 1)每个参数的长度不能超过寄存器的长度,即32位
      • 2)在系统调用号(eax)之外,参数的个数不能超过6个(ebx, ecx,edx,esi,edi,ebp)

一.实验:使用库函数API time()来获取系统当前时间

实验过程&遇到的问题

2.解决办法

见下一个实验的解决办法。

3.代码分析

#include<stdio.h>
#include<time.h>
int main()
{
time_t tt; //t是一个int型的数值,记录当前系统的时间,
struct tm *t; //定义一个 struct tm 类型的指针变量 t
tt = time(NULL); //使用库函数 API time() 来获取 tt
t = localtime(&tt); //调用 localtime() 把tt变成 struct tm 这种结构的格式便于输出为可读格式
printf("time:%d:%d:%d:%d:%d:%d:\n",t->tm_year+1900,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
return 0;
}

二.实验:用汇编方式触发系统调用获取系统当前时间

1.遇到的问题

解决办法

修改代码如下:



可以正常运行:

2.内嵌汇编代码如下

asm volatile(
"mov $0,%%ebx\n\t" //把EBX寄存器清零
"mov $0xd,%%eax\n\t" //EAX寄存器传递系统调用号13
"int $0x80\n\t" //触发系统调用陷入内核执行13号系统调用的内核处理函数
"mov %%eax,%0\n\t" //通过EAX寄存器返系统调用值,把EAX寄存器的值放到tt变量中,即完成了C代码中嵌入汇编代码触发13号系统调用time
:"=m"(tt)
);

三.实验:含两个参数的系统调用(一)

先使用库函数API触发rename系统调用。

代码如下:

#include<stdio.h>
int main()
{
int ret;
char *oldname = "hello.c";
char *newname = "newhello.c";
ret = rename(oldname,newname);
if(ret == 0
printf("Renamed successfully\n");
else
printf("Unable to rename the file\n");
return 0;
}

实验过程

四.实验:含两个参数的系统调用(二)

用嵌入式汇编代码触发rename调用。

代码如下:

#include<stdio.h>
int main()
{
int ret;
char *oldname = "hello.c";
char *newname = "newhello.c";
asm volatile(
"movl %2,%%ecx\n\t" //将newname存入ecx寄存器
"movl %1,%%ebx\n\t" //将oldname存入ebx寄存器
"movl $0x26,%%eax\n\t" //把系统调用号38存入EAX寄存器中
"int $0x80" //执行系统调用陷入内核态,执行38号系统调用的内核处理函数
:"=a"(ret)
:"b"(oldname),"c"(newname)
);
if(ret == 0)
printf("Renamed successfully\n");
else
printf("Unable to rename the file\n");
return 0;
}

实验过程

将汇编代码中的 "=a" 换成 "=m" 之后,再次编译,运行结果如下图:

可以发现,hello.c 变成了 newhello.c ,却显示没有修改成功。其实确实执行了 sys_rename ,返回值0保存到EAX寄存器中。这里的修改失败是指 ret 不等于0。

ret 的限定符是 m ,也就是说 ret 是内存变量。想要使 ret 的值为0,需要先使EAX寄存器的0值传给 ret 。增加代码 “movl %%eax,%0” 如下:

再次编译运行:

遇到的问题

问题原因:在64位系统下去编译32位的目标文件,这样是非法的。

解决方案:用”-m32”强制用32位ABI去编译,即可编译通过。

解决方案:新增加的代码 “movl %%eax,%0” 的上一句汇编语言末尾没有添加"\n\t",添加之后可以正常编译。

五.实验:通用的触发系统调用的库函数syscall

若内核增加一个新的系统调用,libc函数库的版本没有及时更新为其编写API函数,可以利用libc提供的syscall函数直接调用。

syscall函数原型:

extern long int syscall(long int sysno,...) __THROW

sysno是系统调用号,“...”是系统调用所带的参数。

以rename为例来看代码实现:

2019-2020-1 20199324《Linux内核原理与分析》第五周作业的更多相关文章

  1. 2019-2020-1 20199329《Linux内核原理与分析》第九周作业

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

  2. 2019-2020-1 20199329《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...

  3. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  4. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  5. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  6. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  7. 2019-2020-1 20209313《Linux内核原理与分析》第二周作业

    2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  10. 2018-2019-1 20189221《Linux内核原理与分析》第二周作业

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

随机推荐

  1. Java中String类为什么被设计为final?

    Java中String类为什么被设计为final   首先,String是引用类型,也就是每个字符串都是一个String实例.通过源码可以看到String底层维护了一个byte数组:private f ...

  2. MFC 打开Jpg文件

    UpdateWindow(); int height, width; CRect rect;//定义矩形类 CRect rect1; CImage image; //创建图片类 image.Load( ...

  3. javaScript_BOM浏览器对象模型

    BOM:浏览器对象模型 Browser Object Model 用来访问和操作浏览器窗口,使JavaScript有能力与浏览器对话 通过使用BOM ,可以移动窗口,更改状态栏.执行其他不与页面内容发 ...

  4. eclipse配置tomcat详细步骤

    1.下载tomcat9并解压到D盘根目录下 2.Windows——>Preferences——>Server——>Runtime Environments——>Add 3.选择 ...

  5. ModernRNN

    GRU RNN存在的问题:梯度较容易出现衰减或爆炸(BPTT) ⻔控循环神经⽹络:捕捉时间序列中时间步距离较⼤的依赖关系 RNN: \[ H_{t} = ϕ(X_{t}W_{xh} + H_{t-1} ...

  6. Excel Old format or invalid type library 错误原因

    Old format or invalid type library 错误原因 调用excel方法失败,Old format or invalid type library 解决方案: 1,这是Exc ...

  7. D. Minimax Problem(二分+二进制)

    D. Minimax Problem time limit per test 5 seconds memory limit per test 512 megabytes input standard ...

  8. Vus the Cossack and Strings(Codeforces Round #571 (Div. 2))(大佬的位运算实在是太强了!)

    C. Vus the Cossack and Strings Vus the Cossack has two binary strings, that is, strings that consist ...

  9. intellij idea安卓开发配置

    1.java sdk 2.java ndk 3.gradle https://gradle.org/install/#manually 配置properties 删除根目录下android{} htt ...

  10. fscanf的用法

    fscanf用于读取字符串数据流,遇到空白字符(空格' '; 制表符'\t'; 新行符'\n')就停止,若要读取完整的一行数据,可以使用格式控制("%[^\n]%*c"),或者使用 ...