如何在 OS161 中添加 open 系统调用的两个变体?

2024-04-10

从手册页OS161:

Synopsis

#include <unistd.h>
#include <fcntl.h>

int
open(const char *filename, int flags);
int
open(const char *filename, int flags, mode_t mode);

标准c库函数是如何实现的open被定义为:

int open(const char *filename, int flags, ...);

声明:

/*
 * Definition for each syscall.
 * All we do is load the syscall number into v0, the register the
 * kernel expects to find it in, and jump to the shared syscall code.
 * (Note that the addiu instruction is in the jump's delay slot.)
 */

#define SYS_open         45

#define SYSCALL(sym, num) \
   .set noreorder       ; \
   .globl sym           ; \
   .type sym,@function      ; \
   .ent sym         ; \
sym:                ; \
   j __syscall                  ; \
   addiu v0, $0, SYS_##sym  ; \
   .end sym         ; \
   .set reorder

SYSCALL(open, 45)

当发出系统调用时,系统调用调度程序被调用。系统调用调度程序接受一个指向trapframe其中包括发出系统调用之前寄存器的值。其中一个寄存器包含系统调用号,调度程序使用该号来调度到正确的系统调用函数。调度程序看起来像这样:

void
syscall(struct trapframe *tf)
{
    int callno;

    ...

    callno = tf->tf_v0;

    ...

    switch (callno) {
        case SYS_reboot:
        err = sys_reboot(tf->tf_a0);
        break;

        case SYS___time:
        err = sys___time((userptr_t)tf->tf_a0,
                 (userptr_t)tf->tf_a1);

    ...

}

以下注释描述了如何传递参数以及如何返回值:

 * The calling conventions for syscalls are as follows: Like ordinary
 * function calls, the first 4 32-bit arguments are passed in the 4
 * argument registers a0-a3. 64-bit arguments are passed in *aligned*
 * pairs of registers, that is, either a0/a1 or a2/a3. This means that
 * if the first argument is 32-bit and the second is 64-bit, a1 is
 * unused.
 *
 * This much is the same as the calling conventions for ordinary
 * function calls. In addition, the system call number is passed in
 * the v0 register.
 *
 * On successful return, the return value is passed back in the v0
 * register, or v0 and v1 if 64-bit. This is also like an ordinary
 * function call, and additionally the a3 register is also set to 0 to
 * indicate success.
 *
 * On an error return, the error code is passed back in the v0
 * register, and the a3 register is set to 1 to indicate failure.
 * (Userlevel code takes care of storing the error code in errno and
 * returning the value -1 from the actual userlevel syscall function.
 * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)

例如你可以看到sys_reboot被称为tf->tf_a0,那是因为在发出系统调用之前,寄存器a0包含系统调用的第一个(也是唯一的)参数。

为了简单起见,我不会深入讨论细节,因为它可能无关紧要。例如,发出系统调用的过程有点复杂,但我只提到了相关的内容。也不会谈论如何从堆栈中获取参数,因为我在这里不需要它。


我应该实施sys_open系统调用,但我不确定如何知道哪个变体open函数被称为...

我所拥有的只是系统调用号和寄存器的值,其中包括四个参数寄存器、堆栈指针和其他寄存器。

如何确定我面临的是第一个变体(仅具有两个参数)还是第二个变体(具有 3 个参数),以便我可以采取相应的行为?


一些有用的信息:

系统调用的完整代码是here https://github.com/ops-class/os161/blob/master/kern/arch/mips/syscall/syscall.c#L79.

OS161 的整个存储库是here https://github.com/ops-class/os161.

异常处理程序代码在引导期间加载到内存中。

异常处理程序的代码(发出系统调用时运行的第一个代码)是here https://github.com/ops-class/os161/blob/master/kern/arch/sys161/main/start.S#L131.

异常处理程序是一个名为mips_general_handler只是调用一个函数common_exception.

mips_general_handler is here https://github.com/ops-class/os161/blob/master/kern/arch/mips/locore/exception-mips1.S#L86.

common_exception is here https://github.com/ops-class/os161/blob/master/kern/arch/mips/locore/exception-mips1.S#L106.

common_exception将寄存器的所有值推入堆栈,还将指针推入推入值的开头(即传递给正在调用的函数的指针)并调用该函数mips_trap可以找到here https://github.com/ops-class/os161/blob/master/kern/arch/mips/locore/trap.c#L126.

功能misp_trap查找异常的原因,如果是系统调用,则调用该函数syscall这是上面给出的。


首先,OS161 手册页是wrong错误地暗示有两个版本open()功能。只有一个版本open()- C 不支持函数重载,如手册页所暗示的那样。根据 POSIX https://pubs.opengroup.org/onlinepubs/9699919799/functions/openat.html的一个版本open() is

SYNOPSIS
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *path, int oflag, ...);

请注意该手册页如何让您误以为有两个版本open()。没有。对于所谓的“教学操作系统”来说,这种草率确实很糟糕。

The mode如果oflag论证为O_CREAT位设置:

O_CREAT

如果文件存在,则此标志无效,除非如下所述O_EXCL以下。否则,如果O_DIRECTORY未设置文件应 创建为常规文件;文件的用户 ID 应设置为 进程的有效用户ID;文件的组 ID 应 设置为文件父目录的组 ID 或 进程的有效组ID;和访问权限位 (看<sys/stat.h>)的文件模式应设置为值 oflag 参数后面的参数被视为类型mode_t修改如下:对文件模式位执行按位 AND 以及进程文件模式补码中的相应位 创作面具。因此,文件模式中的所有位的对应位 在文件模式中创建掩码设置被清除。当位其他 如果设置了文件权限位,则效果未指定。这 oflag 参数后面的参数不会影响文件是否 可供阅读、写作或两者皆可。实施应 提供一种将文件的组 ID 初始化为文件的组 ID 的方法 父目录。实现可以但不需要提供 将文件的组 ID 初始化为实现定义的方法 调用进程的有效组ID。

假设对于 OS161char *path参数是一个 64 位指针并且两者int and mode_t是 32 位,a0 and a1寄存器应包含path指针参数,a2应包含oflag论证,以及a3应包含mode论证如果O_CREAT位被设置在oflag争论。如果用户进程调用代码没有使用mode论点但确实设置了O_CREAT bit,

注意Linuxopen() syscall https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-5.html正是以这种方式实现的* -mode参数由调用进程设置(如果相关)。

* - 几乎。 Linux实际上实现了open() as openat( AT_FDCWD, ...)。如果OS161提供openat(),你可能应该实施open() as openat( AT_FDCWD, ...) also.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 OS161 中添加 open 系统调用的两个变体? 的相关文章

  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐