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

知识点总结:

  • 系统调用:系统调用是操作系统为用户态进程与硬件设备进行交互提供的一组接口。
  • 系统调用的功能特性:
    • 把用户从底层的硬件编程中解放出来;
    • 极大地提高了系统的安全性;
    • 使用户程序具有可移植性。
  • 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 SPRING框架开发学习笔记:Spring Bean的配置及常用属性

    作为 Spring 核心机制的依赖注入,改变了传统的编程习惯,对组件的实例化不再由应用程序完成,转而交由 Spring 容器完成,在需要时注入应用程序中,从而对组件之间依赖关系进行了解耦.这一切都离不 ...

  2. 吴裕雄--天生自然Django框架开发笔记:Django 安装

    Window 下安装 Django 如果你还未安装Python环境需要先下载Python安装包. 1.Python 下载地址:https://www.python.org/downloads/ 2.D ...

  3. UML-持久框架-目标&关键思想

    1.目标 1).使用模板方法.状态模式.命令模式来设计部分框架 2).介绍对象-关系(O-R)映射中的一些问题 3).使用虚代理实现的滞后具体化 2.关键思想 1).映射(Mapping) 类--表 ...

  4. idea排除要编译的文件

    感觉应该有更好的方式.VS中可以右键文件从项目中排除 如果要恢复选中要恢复的文件,点击 +下的-即可

  5. 用户使用API函数对创建的文件进行读写操作

    HANDLE handle; //定义文件句柄 ]; //定义缓冲区 int i; //接收实际操作的字节数 CString str; //定义字符串变量 handle = ::CreateFile( ...

  6. 吴裕雄--天生自然MySQL学习笔记:MySQL 处理重复数据

    有些 MySQL 数据表中可能存在重复的记录,有些情况允许重复数据的存在,但有时候我们也需要删除这些重复的数据. 防止表中出现重复数据 可以在 MySQL 数据表中设置指定的字段为 PRIMARY K ...

  7. No module named cv2 报错处理

    运行python脚本出现“No module named cv2 ”,这时我们安装下opencv-python依赖即可 python3 -m pip install opencv-python

  8. 2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛 A题

    A - ^&^ Bit operation is a common computing method in computer science ,Now we have two positive ...

  9. PAT B1045 快速排序

    题目如下: 1045 快速排序 (25 point(s)) 著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到 ...

  10. ZJNU 2351 - 快乐

    由题意得,如果有个人从前往后能找到第一个不低于自己等级的任务,就会接取其后所有任务 那么就可以让输入数据处理成递增数列 例如1 3 5 4 6 2 7 7 3 可以处理成1 3 5 5 6 6 7 7 ...