【Pintos】实现自定义 UserProg 系统调用 | 添加 syscall-nr 系统调用号 | 编写新的参数调用宏

news2024/11/18 4:46:40

💭 写在前面:本文讲解的内容不属于 Pintos 的 Project 项目,而是关于 userprog 如何添加系统调用的,学习如何额外实现一些功能到系统调用中以供用户使用。因为涉及到 src/example 下的Makefile 的修改、lib 目录下 syscall-nr 系统调用号的增添以及定义调用宏等操作,所以需要对 Pintos 项目有一定的了解。本文旨在帮助大家 DIY 自己想实现的系统调用,增加到自己的 Pintos 项目中。为了方便讲解,我们添加两个非常简单的系统调用功能,调用的功能其实并不重要,重要的是关注添加系统调用的操作。我们会将下面两个我们自己实现的函数作为系统调用:

int fibonacci(int n)   // 返回斐波那契数列的第n项
int max_of_four_int(int a, int b, int c, int d)  // 返回 a b c d 中的最大值

🔍 前置文章:

【OS Pintos】Pintos 环境准备

【OS Pintos】用户程序是如何工作的 | Pintos 运行原理 | 虚拟内存 | 页函数 | 系统调用

【OS Pintos】Project1 项目要求说明 | 进程中止信息 | 参数传递 | 用户内存访问


Step1:进入 examples 目录

首先我们要进入 example 目录。examples 目录是在 Pintos 目录下的 src 子目录下的。

$ cd pintos/src/examples

Step2:修改 Makefile 文件

添加系统调用,自然需要修改 Makefile 文件,我们可以照着其他用户程序的编写方式去修改:  

$ vim Makefile   # 用vim编辑器打开Makefile

 (打开后如图所示)

我们来分析一下这个 Makefile 文件,我们先看前面的注释……

emm,这似乎是 Pintos 作者留下的注释哈:

大致意思就是:添加新的系统调用接口,需要先将它名字添加到 \textrm{PROGS} 列表中,然后按  name_SRC 的格式添加到资源文件中(name 指的是系统调用的名字)。

 好,我们乖乖听话,按大哥的要求做!

Vim 下输入 i  进入插入模式后,在  \textrm{PROGS} 列表中添加一个文件名,比如取名 additional :

PROGS = cat cmp cp echo halt hex-dump ls mcat mcp mkdir pwd rm shell \
        bubsort lineup matmult recursor additional

按照要求在 \textrm{PROGS} 列表中添加完名字后,还需要将其添加到资源文件中,也在这个 Makefile 里,我们直接往下拉照葫芦画瓢,按格式添加即可:

additional_SEC = additional.c

编辑完成后 !wq  退出 Vim 即可。

Step3: 为新的系统调用添加系统调用编号

记录系统调用编号的文件是 syscall-nr.h,它在 lib 目录下:

$ cd pintos/src/lib   # 进入user目录  (在cse目录下输入)

我们用 Vim 打开它,小心点输别输错了,不然自动创建新的文件就麻烦了:

$ vim syscall-nr.h

我们按照要求,在 enum 里添加两个函数的系统调用编号:

    SYS_FIBONACCI,        
    SYS_MAX_OF_FOUR_INT,

Step4:编写新的系统调用的 API 原型

我们需要在 syscall.h 文件夹中修改,它在进入 lib/user 目录下,走起:

$ cd pintos/src/lib/user   # 进入user目录  (在cse目录下输入)

我们 Vim 进入 syscall.h

$ vim syscall.h

 

 我们给它加上新的接口函数的声明: 

int fibonacci(int n);
int max_of_four_int(int a, int b, int c, int d); 

Step5:为 max_of_four_int 函数定义参数调用宏  syscall4

Pintos 的 syscall 有 4 个参数调用宏,分别是 syscall0syscall1, syscall2, sycall3(数字几就是几个参数)

max_of_four_int 这个函数有 4 个参数要传,加上调用编号的话就是一共要传 5 个参数:

int max_of_four_int(int a, int b, int c, int d);

因为 Pintos 的自带的最多只能传4个,所以我们就不得不实现一个 syscall4 函数。举这个例子函数正式为教会大家学会如何处理 —— 自己实现的函数需要传的参数大于 syscall3 的情况。

这就需要我们手写添加一个 syscall4 的宏。在 syscall.c 里添加 ,文件位置在 src/lib/user 下:

$ cd pintos/src/lib/user   # 进入user目录  

老样子,用 Vim 打开进行编辑:

$ vim syscall.c

这个 syscall.c 的源码内容比较长,我们从前往后慢慢看:

这些就是 Pintos 写好的系统调用宏,分别是无参,一个参数,两个参数,三个参数的系统调用宏。而我们新增的 max_of_four_int  函数需要传递 a,b,c,d 四个参数,而 Pintos 并没有实现,所以这需要我们自己去实现!

 我们仍然是用 照猫画虎大法, 在实现之前我们仔细观察下 syscall3 宏,有助于我们理解,自己实现 syscall4 也能更轻松。

/* Invokes syscall NUMBER, passing arguments ARG0, ARG1, and
   ARG2, and returns the return value as an `int'. */
#define syscall3(NUMBER, ARG0, ARG1, ARG2)                      \
        ({                                                      \
          int retval;                                           \
          asm volatile                                          \
            ("pushl %[arg2]; pushl %[arg1]; pushl %[arg0]; "    \
             "pushl %[number]; int $0x30; addl $16, %%esp"      \
               : "=a" (retval)                                  \
               : [number] "i" (NUMBER),                         \
                 [arg0] "r" (ARG0),                             \
                 [arg1] "r" (ARG1),                             \
                 [arg2] "r" (ARG2)                              \
               : "memory");                                     \
          retval;                                               \
        })

💡 解读:不要被这一大坨宏吓到,后面的 \ 是代码换行,这是为了代码可读性而加的!

我们可以看到函数参数有 NUMBERAGE0AGE1AGE2NUMBER 接收的就是我们的系统调用号,AGE 就是 argument 的简写,就是要接收的参数。

这里是 syscall3,接收三个参数所以这里自然有三个 AGE,我们下面要实现 4 个参数时这里就需要再加一个 "AGE3"。随后 asm volatile 进行 pushl 操作,

注意!参数是 "从右往左" 压入的,即先压 AGE2,再压 AGE1……最后再压 NUMBER

而后面的 addl $16 即需要的空间,每个 int 型参数占 4 个字节,这里加上系统调用号 NUMBER 一共要 pushl 4 个参数,所以需要索要 16 个字节:

(3+1)\times 4=16

通过这里我们就能知道,我们在实现 syscall4 参数调用宏时,会有 5 个参数,那么到时候这里就需要写 addl $16 。好了,开始照猫画虎写 syscall4 宏:

#define syscall4(NUMBER, ARG0, ARG1, ARG2, ARG3)                             \
        ({                                                                   \
          int retval;                                                        \
          asm volatile                                                       \
            ("pushl %[arg3]; pushl %[arg2]; pushl %[arg1]; pushl %[arg0]; "  \
             "pushl %[number]; int $0x30; addl $20, %%esp"                   \
               : "=a" (retval)                                               \
               : [number] "i" (NUMBER),                                      \
                 [arg0] "r" (ARG0),                                          \
                 [arg1] "r" (ARG1),                                          \
                 [arg2] "r" (ARG2),                                          \
                 [arg3] "r" (ARG3)                                           \
               : "memory");                                                  \
          retval;                                                            \
        })

 然后不要急着退出,我们 Step5 还要在这里进行操作。

Step5:编写函数的系统调用 API

我们刚才已经为 max_of_four_int 定义了 syscall4 了,我们还要在 syscall.c 里实现这两个新函数的系统调用接口。我们刚才在 syscall.h 里已经给这两个函数写过函数声明了:

int fibonacci(int n);
int max_of_four_int(int a, int b, int c, int d); 

现在也准备好了 syscall4,我们自然要在 syscall.c 里实现一下它们的系统调用接口。

Fibonacci 函数只有一个参数(没算调用号),使用 Pintos 自带的 syscall1 即可。max_of_four_int 有四个参数(没算调用号),就用我们刚才实现的 syscall4 就行。

这也是为什么我们要 Step by Step 地讲。先定义好系统调用号,然后定义 syscall.h 的系统调用接口,再实现 syscall4,最后再实现 syscall.c 的系统调用接口。按这样的顺序去做不会乱,也不至于写着写着怎么参数突然冒出一个系统调用号,搞得人一脸懵。

 啊哈哈哈哈哈哈,搞定!

Step6:实现这两个函数的功能

在 userprog 下也是有个 syscall.c 文件的,如果你做过 Pintos Project1 你应该会对它很熟悉。

我们需要在 userprog/syscall.c 这写上系统调用的功能实现:

$ cd pintos/src/userprog

至于 Fibonacci 和 max_of_four_int 函数的实现,和本篇博客主题无关(不是C基础教学),代码我直接给出,这不重要仅供参考。

💬 求第 n 个斐波那契数列(非递归法)

int fibonacci(int n)
{
    /* Non-Rec method */
    int a = 1;
    int b = 1;
    int c = 1;
    while (n > 2) {
        c = a + b;
        a = b;
        b = c;
        n--;
    }
    
    return c;
}

 💬 求四数最大值:

int max_of_four_int(int a, int b, int c, int d)
{
        int max = a;  /* Suppose the first number is bigest */
        if (max < b) max = b;
        if (max < c) max = c;
        if (max < d) max = d;

        return max;
}

 实现完后保存退出即可,至此我们的任务就大功告成了。

💭 测试: pintos/src/userprog 下输入:

pintos --filesys-size=2 -p ../examples/additional -a additional -- -f -q run 'additional 10 20 62 40'

🚩 效果演示:

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2022.12.17
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料:Stanford OS Pintos 官方文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/96279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

门诊排队叫号系统,有序叫号就诊,适用医院医院、门诊部、诊所等

排队叫号系统&#xff0c;是将互联网信息技术与门诊预约、签到、提醒、叫号、接诊等环节相结合&#xff0c;实现门诊流程式便捷叫号服务。 为助力门诊营造一个良好有序的就诊环境&#xff0c;打造科学合理的就诊流程&#xff0c;今天给大家推荐一款一款便捷排队叫号系统&#x…

Linux基本权限(2)

Linux基本权限(2) &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要讲解了目录权限&#xff0c;和目录&#…

2022年底,我手里一共负责了30套系统

2022年真是不平凡的一年&#xff0c;往常熙熙攘攘的办公室人越来越少&#xff0c;真是像曹操说的兄弟相继凋零&#xff0c;好似风中落叶啊。 结果人少了&#xff0c;手里的系统一个没少&#xff0c;慢慢年底了&#xff0c;我汇总了一下&#xff0c;手里的系统达到了30来个。 搞…

Linux--基础IO

目录 C文件IO 系统文件IO 接口介绍 系统调用和库函数 文件描述符 open返回值 文件描述符的分配规则 重定向 代码演示 使用dup2系统调用 缓冲区 FILE 理解文件系统 文件系统 inode 软硬链接 静态库和动态库 概念 生成静态库 生成动态库 C文件IO 写文件 #in…

SpringBoot+Prometheus+Grafana 实现自定义监控

1.Spring Boot 工程集成 Micrometer 1.1引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency><groupId>io.micrometer<…

E1. Erase and Extend (Easy Version)(纯暴力+string)

Problem - 1537E1 - Codeforces 这是该问题的简单版本。唯一的区别是对n和k的约束。只有当所有版本的问题都解决了&#xff0c;你才能进行黑客攻击。 你有一个字符串s&#xff0c;你可以对它进行两种类型的操作。 删除字符串的最后一个字符。 复制字符串&#xff1a;s:ss&…

数据结构---堆排序

堆排序JAVA实现和快速排序区别二叉堆的构建&#xff0c;删除&#xff0c;调整是实现堆排序的基础之前博客写了二叉堆&#xff1a; 二叉堆最大堆的堆顶是整个堆中的最大元素。最小堆的堆顶是整个堆中的最小元素。 堆排序步骤&#xff1a; 把无序数组构建成二叉堆。(需要从小到…

ArcGIS基础:等高线数据生成栅格DEM数据

以下操作为生成栅格DEM数据的方法。 一般方法是先创建TIN&#xff0c;然后在转为栅格DEM数据。 原始数据如下&#xff1a;为等高线数据&#xff0c;创建TIN数据需要用到等高线数据的【高程】字段。 声明&#xff1a;数据来源于网络。 工具位于【3D分析工具】下的【TIN】下…

BeanDefinition

1. 前言 Spring最重要的一个概念当属Bean了&#xff0c;我们写的Controller、Service、Dao凡是加了对应注解交给Spring管理的&#xff0c;都是Spring容器中的一个Bean。把我们自己写的类变成一个Bean交给Spring管理有很多的好处&#xff0c;比如我们不用自己去new对象了&#…

ssh+mysql实现的Java web企业人事人力资源管理系统源码+运行教程+参考论文+开题报告

今天给大家演示的是一款由sshmysql实现的Java web企业人事人力资源管理系统&#xff0c;其中struts版本是struts2&#xff0c;本系统功能非常完善&#xff0c;已经达到了可以商用的地步&#xff0c;基本全部实现了整个人力资源管理的所有功能&#xff0c;包括员工档案信息、部门…

jekins集成部署

jekins集成部署1.jekins简介2.Jenkins部署环境3. jekins安装4.配置jekins启动和停止脚本5.插件安装5.1.安装maven插件安装5.2 安装gitee插件5.3 安装Publish Over SSH插件5.4 安装 事件机制插件6.任务构建6.1 构建任务6.2 配置giteeApi令牌6.3 配置gitee源码地址6.4 在build中配…

3D激光里程计其二:NDT

3D激光里程计其二&#xff1a;NDT1. 经典NDT2. 计算方式2.1 2D场景求解:2.2 3D场景求解&#xff1a;3. 其他 NDTReference:深蓝学院-多传感器融合 1. 经典NDT NDT 核心思想&#xff1a;基于概率的匹配。目标是将点集 Y 匹配到固定的点集 X 中。这里的联合概率说的是将 X 划分成…

计算机毕业设计springboot+vue社区疫情防控系统

项目介绍 本系统运用最新的技术springboot框架,此框架是现在社会公司生产中所用的必需框架,非常实用,相比于以前的ssm框架,简单很多。前端框架运用vue框架,vue框架是最近几年非常流行的前端技术,适合很多开发语言。主要可以是系统的前端和后端进行解耦,分离,有利于开发者分别注…

设计模式——中介者模式

中介者模式一、基本思想二、应用场景三、结构图四、代码五、优缺点优点缺点一、基本思想 定义一个中介对象来封装一系列对象之间的交互&#xff0c;使原有对象之间的耦合松散&#xff0c;且可以独立地改变它们之间的交互。中介者模式又叫调停模式&#xff0c;它是迪米特法则的…

Proteus8仿真:51单片机LCD1602显示

51单片机LCD1602显示元器件原理图部分代码main.c工程文件元器件 元器件名称排阻RESPACK-851单片机AT89C51LCD1602LM016L按键BUTTON 原理图部分 LCD1602驱动: HD44780显示主要有8位操作8位两行显示&#xff0c;4位操作8位一行显示&#xff0c;8位操作8位一行显示。 LCD1602主要…

【Python】循环语句

目录 1.while 循环 2. for 循环 3. continue 4. break 1.while 循环 基本语法格式 while 条件&#xff1a; 循环体 条件为真&#xff0c;则执行循环体代码 条件为假&#xff0c;则结束循环 例1&#xff1a;打印 1 - 10 的整数 num 1 while num < 10:print(num)num 1 …

【AI with ML】第 10 章 :创建 ML 模型以预测序列

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

MySQL底层索引

目录 一、什么是索引&#xff1f; 二、MySQL索引结构分析【MySQL底层采用的是BTree】 1、为什么不使用二叉树&#xff1f; 2、为什么不使用红黑树&#xff1f; 3、为什么不使用Hash&#xff1f; 4、BTree与B-Tree的区别&#xff1f; 三、MySQL数据库的表结构、索引、数据 1、M…

基于Sharfetter-Gummel和改进的Sharfetter-Gummel计算对流扩散方程的通量(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

1. Arthas的命令

万恶淫为首&#xff0c;百善孝为先 Arthas命令 可以查看相应的文档: https://arthas.aliyun.com/doc/命令.html 如: https://arthas.aliyun.com/doc/grep.html https://arthas.aliyun.com/doc/cat.html 基础命令 help 查看命令帮助信息 cat 查看当前arthas 系统中的任意文件…