2019-2020-1 20199324《Linux内核原理与分析》第五周作业
第四章 系统调用的三层机制(上)
知识点总结:
- 系统调用:系统调用是操作系统为用户态进程与硬件设备进行交互提供的一组接口。
- 系统调用的功能特性:
- 把用户从底层的硬件编程中解放出来;
- 极大地提高了系统的安全性;
- 使用户程序具有可移植性。
- 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内核原理与分析》第五周作业的更多相关文章
- 2019-2020-1 20199329《Linux内核原理与分析》第九周作业
<Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...
- 2019-2020-1 20199329《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...
- 20169212《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...
- 20169210《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业
2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...
- 2017-2018-1 20179215《Linux内核原理与分析》第二周作业
20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...
- 2019-2020-1 20209313《Linux内核原理与分析》第二周作业
2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...
- 2018-2019-1 20189221《Linux内核原理与分析》第一周作业
Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...
- 《Linux内核原理与分析》第一周作业 20189210
实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...
- 2018-2019-1 20189221《Linux内核原理与分析》第二周作业
读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...
随机推荐
- PAT Advanced 1098 Insertion or Heap Sort (25) [heap sort(堆排序)]
题目 According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, and ...
- Day 1:线程与进程系列问题(一)
一.进程与线程 进程:正在执行的程序称为一个线程,主要负责内存空间的划分. 线程:线程在一个进程中负责代码的执行,就是进程中的一个执行路径. 多线程:在一个进程中有多个线程同时在执行不同的任务(同时指 ...
- delphi 单例模式
unit Singleton; (* 单例模式适用于辅助类, 一般伴随于单元的生命周期 *) interface uses SysUtils; type TSingleton = class publ ...
- ES6 之 函数的扩展 尾调用以及尾递归
函数参数的默认值 function log(x, y) { y = y || 'world' console.log(x + ' ' + y); } log('hello') // hello wor ...
- SQL server 查询常用语句 2019.3.20
SQL查询语句 select ...列名 from 表名 投影查询 select sno num,2019-sage as birthday // 给列起别名 from student: 在每个学生姓 ...
- Java并发分析—ConcurrentHashMap
LZ在 https://www.cnblogs.com/xyzyj/p/6696545.html 中简单介绍了List和Map中的常用集合,唯独没有CurrentHashMap.原因是CurrentH ...
- PHP核心配置详解
基本配置-语法 1:大小写敏感 directive = value 2:运算符 | & ~ ! 3:空值的表达方式 foo = ; foo = none; foo = "none&q ...
- MySQL--基础SQL--DML
1.插入记录 INSERT INTO tablename (fields1, fields2, ..., fieldsn) VALUES (value1, value2, ..., valuen) 例 ...
- 4418之Android Eclipse导入应用程序在开发板上调试
由于在开发板上 LEDtest 应用已经默认安装了,所以在开发板上调试已安装应用的时候,需要做一下处理才能够正常连接.基于迅为iTOP4418开发板如下图所示,在打开工程“ledtest”,打开“bi ...
- 17.3.12---urlparse模块的URL下载
1---urlparse模块是一个解析与泛解析Web网址URL字符串的一个工具 urlparse模块会将一个普通的url解析为6个部分,返回的数据类型都是元祖,同时,他还可以将已经分解后的url在组合 ...