2018-2019-1 20189215《Linux内核原理与分析》第五周作业
《庖丁解牛》第四章书本知识总结
- 系统调用的三层机制
API(应用程序编程接口)
中断向量(系统调用处理入口)
服务程序(系统调用内核处理系统)
- 计算机的硬件资源是有限的,为了减少有限资源的访问和使用冲突,CPU和操作系统必须提供一些机制对用户程序进行权限划分,Linux系统采用了Intel x86 CPU的0和3两个特权级别,分别对应内核态和用户态。
- 用户态和内核态很显著的区分方法
CS:EIP的指向范围(对于32位的X86机器):
- 内核态下可以访问0x00000000~0xffffffff的地址空间,共4GB。
- 用户态下只能访问0x00000000~0xbfffffff的地址空间,不能访问从0xc0000000开始的地址空间。
- 一般来说,进入内核态是由中断触发的,系统调用是一种特殊的中断。
- 中断的类别
硬件中断:在用户态进程执行时,硬件中断信号到来,进入内核态,就会执行这个中断对应的中断服务例程。
软中断(trap的方式):用户态程序执行的过程中,调用了一个系统调用,陷入了内核态。
- Linux下系统调用通过int0x80中断完成,中断保存了用户态CS:EIP的值,以及当前的堆栈段寄存器的栈顶,将EFLAGS寄存器的当前值保存到内核堆栈里,同时把当前的中断信号或者是系统调用的终端服务程序的入口加载到CS:EIP中,把当前的堆栈段SS:ESP也加载到CPU里,这些都是由中断信号或者是int指令来完成的。完成后,当前CPU在执行下一条指令时就已经开始执行中断处理程序的入口了,这时对堆栈的操作已经是内核堆栈操作了,
SAVE_ALL
就是内核代码,完成中断服务,如果没有发生进程调度,执行restore_all
恢复中断现场,然后iret
返回到原来的状态;如果发生了进程调度,当前的这些状态就会暂时地保存在系统内核堆栈里,当下一次发生进程调度有机会再切换回当前进程时,执行restore_all
和iret
,这样中断处理过程就执行结束。 - 系统调用通过系统调用号进行区分,通过
EAX
寄存器传递。 - 普通函数调用是通过将参数压栈的方式传递的,而系统调用因为在用户态和内核态下使用不同的堆栈,无法通过参数压栈的方式进行传递,而是通过比较特殊的寄存器传递参数的方式进行。
- 参数按照顺序赋值给
EBX
、ECX
、EDX
、ESI
、EDI
、EBP
,参数的个数不能超过6个,否则的话全部参数应该依次放在一块连续的内存区域里,同时在寄存器EBX
中保存指向该内存区域的指针。
实验:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
看了本课程教材之后,我想试试使用超过6个参数的系统调用,可是失败了,具体过程如下:
- 先写了如下代码:
#include <stdio.h>
int main()
{
int ret;
char* n[8] = {"1","2","3","4","5","6","7","8"};
ret = mkdir(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8]);
if(ret == 0)
printf("mkdir successfully!\n");
else
printf("unable to mkdir.\n");
return 0;
}
结果如下:
好像有点不对?试试Linux系统命令:
Linux命令是可以的呀,难道是mkdir系统调用只能传递一个参数吗?
- 编写了嵌入汇编的代码
#include <stdio.h>
int main()
{
int ret;
char* name[8] = {"1","2","3","4","5","6","7","8"};
asm volatile(
"movl %1,%%ebx\n\t"
"movl $0x27,%%eax\n\t"
"int $0x80"
:"=a"(ret)
:"m"(name) //name数组的地址放入内存变量
);
if(ret == 0)
printf("mkdir successfully!\n");
else
printf("unable to mkdir.\n");
return 0;
}
果不其然,结果还是相同:
将代码修改一下,嵌入汇编中的name
替换为name[2]
,重新编译运行,得到如下结果:
从这个结果来看,大约mkdir系统调用的参数无法这样传输多个。
mkdir
系统调用传递两个参数
经过搜索,mkdir
系统调用可以传递的两个参数是文件夹名
和文件夹权限
,因此编写代码如下:
#include <stdio.h>
int main()
{
int ret;
ret = mkdir("1",0755);
if(ret == 0)
printf("mkdir successfully!\n");
else
printf("unable to mkdir.\n");
return 0;
}
权限0755代表只有所有者才有读,写,执行的权限,组群和其他人只有读和执行的权限。编译、运行得到了想要的结果:
- 继续编写嵌入汇编代码
#include <stdio.h>
int main()
{
int ret;
char* name = "1";
int mod = 0755;
asm volatile(
"movl %2,%%ecx\n\t"
"movl %1,%%ebx\n\t"
"movl $0x27,%%eax\n\t"
"int $0x80"
:"=a"(ret)
:"b"(name),"c"(mod)
);
if(ret == 0)
printf("mkdir successfully!\n");
else
printf("unable to mkdir.\n");
return 0;
}
结果相同:
其他想法
本次实验和书本学习,我学到了不少东西,比如mkdir
系统调用的两个参数,再比如查看目录的相关权限可以采用命令ls -lD
,或者直接用ls -la
,更学到了Linux系统中系统调用的三层机制,受益匪浅,也有一个小猜想:Linux系统中的mkdir命令,在添加了多个参数时,是否是通过多次调用mkdir系统调用执行的?还望看到的老师同学们、朋友们能予以解答。
参考资料
2018-2019-1 20189215《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语言程序并分析其汇编指令执行过程 因 ...
随机推荐
- JS Date parse
因为JS中的Date转换格式没有“-”这种间隔符,Date.parse会生成NAN,所以只能进行转换. <script type="text/javascript"> ...
- VC++ 6.0创建MFC工程时的初级备要点(二)
在看到一个MFC工程时,可能根据上一篇文章已经知道了哪些是重要的,那些是在创建工程的时候已经被初始化的!!下面介绍一下在看代码的过程的策略!!这里假设创建的基于多对话框的MFC工程名为test ...
- 小游戏——js+h5[canvas]+cs3制作【五子棋】小游戏
五子棋小游戏学习—— 有一个问题是,棋盘线的颜色,在canvas中,明明设置了灰色,但在我的预览中还是黑色的,很重的颜色. 以下是复刻的源码: <!DOCTYPE html> <ht ...
- c# SQL Server数据库操作-数据适配器类:SqlDataAdapter
SqlDataAdapter类主要在MSSQL与DataSet之间执行数据传输工具,本节将介绍如何使用SqlDataAdapter类来填充DataSet和MSSQL执行新增.修改..删除等操作. 功能 ...
- java设计模式----迭代子模式
顺序访问聚集中的对象,主要用于集合中.一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问. 迭代子模式为遍历集合提供了统一的接口方法.从而使得客户端不需要知道聚集的内部结构就能 ...
- angularJs初体验,实现双向数据绑定!使用体会:比较爽
使用初体验:ng 双向数据绑定: 最简单的双向数据绑定:(使用默认模块控制) <body ng-app> <input type="text" ng-model= ...
- sql 中如何将返回的记录某一条置顶
将table1中id 为2的记录置顶select * from table1order by case when id='2' then 0 else 1 end 例子:将已发布的置顶,status ...
- c# 公共方法
MyMeans using System; using System.Collections.Generic; using System.Text; using System.Windows.Form ...
- (2.12)Mysql之SQL基础——存储过程条件定义与错误处理
转自:博客园桦仔 5.存储过程条件定义与错误处理 -- (1)定义 [1]条件定义:declare condition_name condition for condition_value;[2]错误 ...
- sql server 2008维护计划配置
转自:https://blog.csdn.net/yunye114105/article/details/6594826 一:目标任务: 使用SQL Server 2008自带的维护计划自动备份数据库 ...