【Pintos】实现自定义 UserProg 系统调用

news2024/9/29 23:37:00

💭 写在前面:本文讲解的内容不属于 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 中的最大值

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

🔍 前置文章:

【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/96443.html

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

相关文章

搜索二叉树详解

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位大佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 文章目录一、搜索二叉树框架二、搜索二叉树概念三、搜索二叉树操作①Erase②Find递归③Insert递归④Erase递归&#xff0c;比Erase更简洁⑤析构函数⑥…

unity学习笔记--day01

今天学习制作了一个简单的抽卡功能&#xff0c;学习结束后目录结构如下&#xff1a; .mate文件是unity生成的配置文件&#xff0c;不用管 制作第一张卡片 创建一个空物体&#xff0c;改名为Card。 在Card下挂载以下UI组件&#xff1a; 编写数据脚本并挂载&#xff0c;unity采用…

Nginx教程(4)—Keepalived

文章目录4.1 高可用集群架构Keepalived双机主备原理4.2 安装Keepalived4.3 Keepalived核心配置文件4.4 Keepalived实现双主机主备高可用测试4.5 高可用集群架构Keepalived双主热备原理Nginx教程一 Nginx教程二 Nginx教程三 4.1 高可用集群架构Keepalived双机主备原理 我们知道…

【计算机毕业设计】78.汽车租赁系统源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 目 录 摘 要 前 言 第1章 概述 1.1 研究背景 1.2 研究目的 1.3 研究内容 第二章 开发技术介绍 2.1 Java技术 2.2 Mysql数据库 2.3 B/S结构 2.4 SSM框架 第三章 系统分析 3.1 可行性分析 3.1.1 技术…

UnrealUBlueprintAsyncActionBase的使用

实现异步调用&#xff0c;之前我们介绍过一种FLatentActionInfo的方法&#xff0c;还有另外一种UBlueprintAsyncActionBase方法&#xff0c;可以实现异步节点&#xff0c;用于异步监听然后进行回调。按照如下步骤进行使用&#xff0c;我们同样以Delay一定帧数&#xff0c;并每帧…

面对新技术,必须找到与其发展相辅相成的长期主义的方法

从Meta股价的一路走低到扎克伯格发布的头显并不被用户买账&#xff0c;Facebook全力拥抱Meta正在经历一场过山车。   扎克伯格和他所带领下的Meta遭遇到的如此多的困境和难题&#xff0c;越来越多地让我们开始相信&#xff1a;所谓的元宇宙并非是一蹴而就的&#xff0c;它是一…

【云原生 Kubernetes】基于 Minikube 搭建第一个k8s集群

一、前言 对于k8s来说&#xff0c;搭建方式有多种&#xff0c;如果是生产环境&#xff0c;一般来说&#xff0c;至少需要3台节点确保服务的高可用性&#xff0c;常用的搭建方式列举如下&#xff08;提供参考&#xff09;&#xff1a; kubeadm搭建&#xff08;推荐&#xff09; …

postman测试环境的创建及发送请求方式

目录 一、创建工作环境 1、打开postman&#xff0c;点击工作区 2、点击新建 3、添加名字&#xff0c;点击创建 4、工作区可以自由切换工作区 5、点击创建发送请求 6、更换请求方式 7、保存测试 二、测试发送请求&#xff0c;使用的时候服务一定要启动 1、普通传参&…

C++ 类型转换

目录 C语言中的类型转换 为什么C需要四种类型转换 C&#xff1a;命名的强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast C语言中的类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c…

信息学奥赛一本通——1163:阿克曼(Ackmann)函数

文章目录1163&#xff1a;阿克曼(Ackmann)函数【题目描述】【输入】【输出】【输入样例】【输出样例】分析代码1163&#xff1a;阿克曼(Ackmann)函数 时间限制:1000ms内存限制:65536KB提交数:24804通过数:20247时间限制: 1000 ms 内存限制: 65536 KB 提交数: 24804 通过数: 202…

第三十章 linux-模块的文件格式与EXPORT_SYMBOL的实现

第三十章 linux-模块的文件格式与EXPORT_SYMBOL的实现 文章目录第三十章 linux-模块的文件格式与EXPORT_SYMBOL的实现模块的文件格式EXPORT_SYMBOL的实现模块的文件格式 以内核模块形式存在的驱动程序&#xff0c;比如demodev.ko&#xff0c;其在文件的数据组织形式上是ELF&am…

数据结构---快速排序

快速排序分治法思想基准元素的选择元素交换双边循环法JAVA实现单边循环法JAVA实现快速排序也是从冒泡排序演化而来使用了 分治法&#xff08;快的原因&#xff09;快速排序和冒泡排序共同点&#xff1a;通过元素之间的比较和交换位置来达到排序的目的。 快速排序和冒泡排序不同…

JavaWeb核心:HTTPTomcatServlet

HTTP 概念: Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则。 HTTP-请求数据格式 HTTP-响应数据格式 响应状态码的大的分类 常见的响应状态码 Tomcat 简介 概念: Tomcat是Apache 软件基金会一个核心项目&#…

【云原生】Prometheus 自定义告警规则

文章目录一、概述二、告警实现流程三、告警规则1&#xff09;告警规则配置1&#xff09;监控服务器是否在线3&#xff09;告警数据的状态四、实战操作1&#xff09;下载 node_exporter2&#xff09;启动 node_exporter3&#xff09;配置Prometheus加载node_exporter4&#xff0…

这样也可以让图像正向扩散

🍿*★,*:.☆欢迎您/$:*.★* 🍿 怎样的扩散取决于b是不是随机噪声 是随机噪声 则是扩散模型 如stable diffision 如果是非噪声则是方向模型 方向模型是指 在已知几个连续的输入 后可以通过模型的辅助预测扩散的方向 而 stable diffision 是通过预测反扩散方向 本质就…

VS2017中OpenCV编程插件Image Watch安装和使用介绍

安装 下载适合vs2017最新版本的Image Watch(ImageWatch.vsix)&#xff0c;下载地址 安装ImageWatch&#xff0c;双击ImageWatch.vsix进行安装即可&#xff1b; 使用 打开一个OpenCV工程&#xff0c;在Debug下设置断点&#xff0c;通过view -> other windows -> Image W…

基于51单片机宠物自动投料喂食器控制系统仿真设计( proteus仿真+程序+讲解视频)

基于51单片机宠物自动投料喂食器控制系统仿真设计( proteus仿真程序讲解视频&#xff09; 仿真图proteus 7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0029 视频讲解 基于51单片机的宠物自动投料喂食器控制系统proteu…

数据结构—最小生成树

目录 一、生成树 二、最小生成树&#xff08;代价最小树&#xff09; 三、求最小生成树 1、Prim算法&#xff08;普里姆&#xff09; 2.Kruskal 算法&#xff08;克鲁斯卡尔&#xff09; 3.Prim算法和Kruskal算法对比 一、生成树 连通图的生成树是包含图中全部顶点的一个…

[附源码]Nodejs计算机毕业设计基于框架的秧苗以及农产品交易网站Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

算法分析专业工具——大O记法

本文内容借鉴一本我非常喜欢的书——《数据结构与算法图解》。学习之余&#xff0c;我决定把这本书精彩的部分摘录出来与大家分享。 写在前面 从之前的章节中我们了解到&#xff0c;影响算法性能的主要因素是其所需的步数。 然而&#xff0c;我们不能简单地把一个算法记为“…