哈工大李治军老师操作系统实验-系统调用(步骤详细和注释代码)

本文主要是介绍哈工大李治军老师操作系统实验-系统调用(步骤详细和注释代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、搞清楚系统调用这个实验叫我们干什么活(我差不多2个小时才搞清楚实验目的):
1.添加两个系统调用:sys_iam()和sys_whoami()。
2.自己写iam.c和whoami.c测试这两个系统调用。
3.在Bochs上用testlab2.sh来测试并统计得分。
4.回答2个问题。

二、通过实验目的我们应该修改或添加以下文件:
1.添加3个文件: who.c; iam.c; whoami.c
2.修改: unistd.h; system_call.s;sys.h ; Makefile

三、我将根据系统调用的执行过程进行实验,以进行sys_iam()为例。
1、在Bochs里,用户态下运行测试代码iam.c ,此时当前程序特权级CPL = 3 ,注意代码的注释要用/* */,不能用//,就这个注释我第一次用//,编译的时候一大堆错误,后来一处一处的改,真是蛋疼呀。

#define __LIBRARY__
#include<unistd.h>
#include<stdio.h>   
#include<errno.h>/* 功能:用户态文件,测试系统调用iam() */  /* 系统调用: */
/* 第一个是函数返回值类型,第二个为函数名,第三个是参数1的数据类型,第四个是参数1的名称,依次类推 */
_syscall1(int,iam,const char*,myname)#define NAMELEN 50    /* 定义最大长度为50 */
char myname[NAMELEN] = {0}; /* 用户态下,存储名字,并且要初始化 *//* argc是命令行参数的个数,argv存储了所有的命令行输入的所有参数的值 */
/* 比如./iam warm-like-spring  :得到argc=2,argv[0]=./iam,argv[1]=warm-like-spring */
int main(int argc, char* argv[])
{int res = 0;    /* 用于接受系统调用后的返回值 */unsigned int namelen = 0;  /* 名字的实际长度 */if(argc < 2){printf("Input arguments is less!\n");return -1;}else {while(argv[1][namelen] != '\0'){       /* 读取并拷贝main参数接收的输入名字字符串 */myname[namelen] = argv[1][namelen];++namelen;}printf("before systemcall, myname: %s, namelen: %d in iam.c\n",myname,namelen);res = iam(myname);  /* 传递拷贝的参数进行调用 */}if(res == -1) printf("systemcall have bug, res:%d, errno:%d\n",res,errno);  /* 打印对应的错误信息码 */elseprintf("systemcall success, res:%d\n",res);return 0;
}

2、当执行到iam(myname)的时候,开始执行

_syscall1(int,iam,const char*,myname)

这行代码会去执行unistd.h里的如下代码,这段代码会把type替换为int,name替换为iam,atype替换成const char*, a替换为myname。并将__NR_##name替换为__NR_iam。__NR_iam就是对应的系统调用号。并且遇到int $0x80后进行中断处理。

#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \: "=a" (__res) \: "0" (__NR_##name),"b" ((long)(a))); \
if (__res >= 0) \return (type) __res; \
errno = -__res; \
return -1; \
}

所以我们需要在hdc/usr/include 目录下修改unistd.h,添加系统调用号:

/* 添加系统调用号 */
#define __NR_whoami 72 
#define __NR_iam 73

提示:不能直接在oslab直接直接修改,要修改虚拟的,通过在oslab目录下,在终端里执行下面的命令,之后找到hdc/usr/include里的unistd.h进行修改。

sudo ./mount-hdc

注:在int 0x80指令调用前,先将宏__NR_iam传递给eax,用于后面system_call调用时查找sys_call_table数组里面的系统函数指针,也就是区分是哪个系统调用。触发int $0x80之后通过kernel/sched.c里的set_system_gate(0x80,&system_call)等等一系列处理,将system_call函数地址写到0x80对应的中断描述符里,即当中断0x80发生后,就自动调用system_call代码。这部分我还没学到,细节不是很了解,各位同行见谅。总的来说,使当前优先级CPL=0,满足DPL>=CPL;程序就成功进入内核态运行了。

3、因为执行int $ 0x80指令,自动调用system_call函数,所以我们还需要修改system_call.s代码。修改如下

nr_system_calls = 74  # 新增2个系统调用

注:在执行system_call时,我们要关心如下代码

call sys_call_table(,%eax,4)  # 系统调用关键代码:相当于call sys_call_table + 4 * %eax

这里的eax里已经存储了宏__NR_iam也就是73。因为函数指针32位环境为4个字节,所以要乘4才能在系统调用表里根据地址字节偏移量找到对应的sys_iam函数指针进行sys_iam系统函数的调用。

4、修改linux-0.11/include/linux/sys.h。sys.h
注:在sys_call_table[]里的添加函数指针的顺序要和unistd.h里的系统调用号顺序一致。

5、最后调用linux-0.11/kernel/who.c里的sys_iam()。

/* 功能:核心态文件,在who.c里实现系统调用sys_iam()与sys_whoami() */#include<errno.h>         /* linux-0.11/include */
#include<unistd.h>
#include<asm/segment.h>  /* linux-0.11/include/asm */
#include<linux/kernel.h>
/* 直接包含的头文件是到linux-0.11/include目录 */#define MAXLEN 23
char username[MAXLEN+1] = {0};        /* 内核态下,存储名字 */int sys_iam(const char* myname){   /* myname为_syscallx调用时保存好了的 */printk("sys_iam run......\n");unsigned int i = 0;unsigned int namelen = 0;/* get_fs_byte(const char * addr) 从用户空间逻辑地址addr取出一个字节数据 */while(get_fs_byte(myname+namelen)!='\0')++namelen;                          if(namelen > MAXLEN){errno = EINVAL;    /* #define EINVAL  22 : Invalid argument */   return -EINVAL;}printk("namelen:%d\n",namelen);  /* 核心态,用printk() */while(i < namelen){username[i] = get_fs_byte(myname+i);  /* 将用户态下传递的字符串参数拷贝到内核中保存 */++i;}username[i] = '\0';printk("username: %s\n",username);return namelen;
}int sys_whoami(char* myname, unsigned int size){printk("sys_whoami run......\n");unsigned int i = 0;unsigned int namelen = 0;while(username[namelen]!='\0')++namelen;if(size < namelen){   /* size小于所需的拷贝空间 */errno = EINVAL;return -EINVAL;}for(; i <= namelen; ++i){put_fs_byte(username[i], myname+i); /* 将内核态里的数据拷贝到用户态文件里 */}printk("namelen: %d\n",namelen);return namelen;
}

6、修改Makefile,这里不多说了,实验楼里很清楚的,复制粘贴的体力活。
7、保存好所有文件,进入oslab/linux-0.11重新编译内核。如果出错在根据错误debug。如果最后没错,出现sync就OK了。

cd linux-0.11
make all

8、回到oslab目录,./run运行Bochs,在里面编译并测试iam.c和whoami.c。

cd ..
sudo umount hdc  /* 卸载 mount hdc */
./run

测试结果
补充:iam.c和whoami.c必须要放到 oslab/hdc/user/root目录里。
通过命令行打开hdc

sudo ./mount-hdc

之后将在ubuntu里写好的iam.c和whoami.c拷贝到 oslab/hdc/user/root。之后命令行卸载mount-hdc

sudo ./umount hdc

补充上whoami.c代码

#define __LIBRARY__
#include<unistd.h>
#include<stdio.h>
#include<errno.h>/* 功能:用户态文件,测试系统调用whoami() */_syscall2(int, whoami, char*, myname, unsigned int, size)#define SIZE 23int main(int argc, char** argv)
{char myname[SIZE+1] = {0}; /* 定义初始化 */unsigned int res = 0;res = whoami(myname, SIZE+1);if(res == -1)printf("systemcall have bug, res:%d, errno:%d\n",res,errno); else{printf("systemcall success.\n"); /*如果要执行testlab2.sh来测试,要把这一行注释掉*/printf("%s\n",myname);}return 0;
}

9、用testlab2.sh脚本测试。注释掉whoami.c里对应的代码后,重新将whoami.c拷贝到hdc/user/root目录里,之后再Bochs里重新编译该文件。

gcc -o whoami whoami.c 
chmod +x testlab2.sh
./testlab2.sh

脚本测试结果
10、好了,现在可以回答另外实验报告需要回答的2个问题了:
1、通过查看unistd.h文件代码,我们发现有

_syscall0(type,name)
_syscall1(type,name,atype,a)
_syscall2(type,name,atype,a,btype,b)
_syscall3(type,name,atype,a,btype,b,ctype,c)

可以看出后面的数字为0~3,所以最多可以传递3个参数。可以通过添加_syscall4()等等来扩展。
2、以上步骤可以推广到添加系统调用foo()的步骤。
有问题可以留言讨论。

这篇关于哈工大李治军老师操作系统实验-系统调用(步骤详细和注释代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/351461

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同