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语言程序并分析其汇编指令执行过程 因 ...
随机推荐
- Linux环境创建交换分区
最近在准备在移动端跑一下深度学习训练好的模型,在RK3399的板子上安装scipy时报错.网上查了一下,由于内存不足导致,做个交换分区就搞定了.那么如何做交换分区呢.话不多说,直接开撸. ------ ...
- Linux(CENTOS7) NodeJs安装
1.下载NodeJs 官网下载地址:http://nodejs.cn/download/ 2.上传到linux系统 我这里上传到/disk/nodejs目录下面的,上传工具使用的xftp. 3 ...
- vscode-wechat 小程序开发提示工具 vscode 安装
vscode 安装 vscode-wechat vscode-wechat 小程序开发提示工具 ---- 有了小程序开发提示,开发很方便 https://segmentfault.com/a/1190 ...
- 两个exe共享内存数据
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- winform操作windows系统计算器
winform对系统计算器的调用,启动,最大化最小化显示,在mainwindow设置topmost=true时,正常显示计算器并置顶. /// <summary> /// 获取窗体的句柄函 ...
- 协程与异步IO
协 程 协程,又称微线程,纤程. 协程的优势: 协程的特点在于是一个线程执行. 协程的最大优势是极高的执行效率,因为子程序切换不是线程切换,而是由 ...
- CF round #622 (div2)
CF Round 622 div2 A.简单模拟 B.数学 题意: 某人A参加一个比赛,共n人参加,有两轮,给定这两轮的名次x,y,总排名记为两轮排名和x+y,此值越小名次越前,并且对于与A同分者而言 ...
- h5-立方体
1.制作一个立方体:首先要有6个面 <div class="box"> <div class="front">front</div ...
- 注意力机制和Seq2seq模型
注意力机制 在"编码器-解码器(seq2seq)"⼀节⾥,解码器在各个时间步依赖相同的背景变量(context vector)来获取输⼊序列信息.当编码器为循环神经⽹络时,背景变量 ...
- 01 语言基础+高级:1-9 网络编程_day11【网络编程】
day11[网络编程] 主要内容 软件架构CS/BS 网络通信三要素 TCP通信 Socket套接字 ServerSocket 教学目标 能够辨别UDP和TCP协议特点 能够说出TCP协议下两个常用类 ...