首页 > 其他分享 >xv6 如何进入系统调用,并设置参数

xv6 如何进入系统调用,并设置参数

时间:2023-04-20 20:14:12浏览次数:43  
标签:调用 return exec 用户 argv xv6 参数 内核

# Initial process that execs /init.
# This code runs in user space.

#include "syscall.h"

# exec(init, argv)
.globl start
start:
        la a0, init
        la a1, argv
        li a7, SYS_exec
        ecall

# for(;;) exit();
exit:
        li a7, SYS_exit
        ecall
        jal exit

# char init[] = "/init\0";
init:
  .string "/init\0"

# char *argv[] = { init, 0 };
.p2align 2
argv:
  .long init
  .long 0

在这段代码中,通过ecall指令进入内核。
然后,会执行uservec、usertrap和syscall函数。
暂时先看syscall

void
syscall(void)
{
  int num;
  struct proc *p = myproc();

  num = p->trapframe->a7;
  if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
    p->trapframe->a0 = syscalls[num]();
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

因为a7中保存的是sys_exec,所以这里会调用sys_exec函数(通过函数指针表)


uint64
sys_exec(void)
{
  char path[MAXPATH], *argv[MAXARG];
  int i;
  uint64 uargv, uarg;

  if(argstr(0, path, MAXPATH) < 0 || argaddr(1, &uargv) < 0){
    return -1;
  }
  memset(argv, 0, sizeof(argv));
  for(i=0;; i++){
    if(i >= NELEM(argv)){
      goto bad;
    }
    if(fetchaddr(uargv+sizeof(uint64)*i, (uint64*)&uarg) < 0){
      goto bad;
    }
    if(uarg == 0){
      argv[i] = 0;
      break;
    }
    argv[i] = kalloc();
    if(argv[i] == 0)
      goto bad;
    if(fetchstr(uarg, argv[i], PGSIZE) < 0)
      goto bad;
  }

  int ret = exec(path, argv);

  for(i = 0; i < NELEM(argv) && argv[i] != 0; i++)
    kfree(argv[i]);

  return ret;

 bad:
  for(i = 0; i < NELEM(argv) && argv[i] != 0; i++)
    kfree(argv[i]);
  return -1;
}

这个sys_exec的返回值会被syscall保存在p->trapframe->a0
内核将控制权返回给用户空间,用户空间的exec()调用根据a0中的值得到结果。


内核函数argint、argaddr和argfd从陷阱帧中检索第 n 个系统调用参数,分别作为整数、指针或文件描述符。它们都调用argraw来检索适当的已保存用户寄存器(位于kernel/syscall.c:35)。

static uint64
argraw(int n)
{
  struct proc *p = myproc();
  switch (n) {
  case 0:
    return p->trapframe->a0;
  case 1:
    return p->trapframe->a1;
  case 2:
    return p->trapframe->a2;
  case 3:
    return p->trapframe->a3;
  case 4:
    return p->trapframe->a4;
  case 5:
    return p->trapframe->a5;
  }
  panic("argraw");
  return -1;
}

这里的意思是:内核开发者在写一个内核函数时,会指定一些参数,那么这些参数就是这个内核函数的调用约定。这些参数需要在调用这个内核函数之前就提前放置在寄存器中。例如下面这段代码,用户在调用系统调用sys_exec之前需要知道这个系统调用的调用约定,然后根据约定把参数放置在正确的寄存器中。然后调用ecall指令来进入内核.

start:
        la a0, init
        la a1, argv
        li a7, SYS_exec
        ecall

然后在内核函数被调用时,通过argint等函数来从寄存器中进行读取。

int sys_my_syscall(void) {
    int arg1, arg3;
    char *arg2;

    // 从陷阱帧中提取参数
    argint(0, &arg1);
    argaddr(1, (uint64 *)&arg2);
    argint(2, &arg3);

    // 在这里处理您的系统调用逻辑

    return 0;
}

某些系统调用传递指针作为参数,内核必须使用这些指针来读取或写入用户内存。例如,exec系统调用将指向用户空间字符串参数的指针数组传递给内核。这些指针带来了两个挑战。首先,用户程序可能存在缺陷或恶意行为,并可能向内核传递无效指针或用于欺骗内核访问内核内存而非用户内存的指针。其次,xv6 内核页表映射与用户页表映射不同,因此内核无法使用普通指令从用户提供的地址加载或存储数据。

内核实现了将数据安全地从用户提供的地址传输到内核并返回的函数。fetchstr是一个例子(位于kernel/syscall.c:25)。诸如exec之类的文件系统调用使用fetchstr从用户空间检索字符串文件名参数。fetchstr调用copyinstr来完成繁重的工作。

copyinstr(位于kernel/vm.c:398)从用户页表pagetable中的虚拟地址srcva复制最多max字节的数据到dst。
由于pagetable不是当前页表,copyinstr使用walkaddr(通过调用walk)在pagetable中查找srcva,得到物理地址pa0。内核将每个物理 RAM 地址映射到相应的内核虚拟地址,因此copyinstr可以直接从pa0复制字符串字节到dst。

这段话的意思是,walkaddr在用户页表中查找指定的指针地址srcva,并且通过页表寄存器计算出物理地址pa0
然后将物理地址映射到内核的虚拟地址中。所以就完成了从用户指定的虚拟地址指针srcva将数据拷贝到内核虚拟地址中。

walkaddr(位于kernel/vm.c:104)检查用户提供的虚拟地址是否是进程的用户地址空间的一部分,因此程序无法欺骗内核去读取其他内存。类似地,copyout函数将数据从内核复制到用户提供的地址。

总结起来,内核处理用户空间传递的参数和指针的方法如下

  1. 通过argint、argaddr和argfd函数从陷阱帧中获取系统调用参数。

  2. 对于涉及传递指针的系统调用,内核实现了安全地将数据从用户提供的地址传输到内核并返回的函数。例如,fetchstr函数用于从用户空间检索字符串文件名参数。

  3. fetchstr调用copyinstr来实际执行数据的拷贝工作。copyinstr从用户页表pagetable中的虚拟地址srcva复制数据到dst。

  4. copyinstr使用walkaddr在pagetable中查找srcva,得到物理地址pa0,并确保用户提供的虚拟地址是进程的用户地址空间的一部分,以防止程序欺骗内核访问其他内存。

  5. copyinstr可以直接从pa0复制字符串字节到dst,因为内核将每个物理 RAM 地址映射到相应的内核虚拟地址。

  6. 另一个函数copyout用于将数据从内核复制到用户提供的地址。

标签:调用,return,exec,用户,argv,xv6,参数,内核
From: https://www.cnblogs.com/ijpq/p/17338143.html

相关文章

  • 你也可以动手参数有效微调:LoRA、Prefix Tuning、P-Tuning、Prompt Tuning
    Part1前言随着大语言模型的流行,如何让大模型在消费级GPU上进行微调训练成为了热点。掌握参数有效微调成为每个自然语言处理工程师必不可少的技能,正好huggingface开源了一个PEFT库,让我们也能够自己动手去了解参数有效微调。接下来以中文情感分析(二分类)去了解下参数有效微调。使......
  • xv6操作系统启动过程
    当按下系统电源按键后,做一些硬件层面的配置和初始化:上电复位:在开机时,计算机进行硬件复位,确保寄存器和其他硬件组件处于初始状态。检查和测试硬件:计算机进行一系列硬件检查和自检操作,以确保硬件组件功能正常。这可能包括内存检测、CPU测试等。初始化硬件组件:初始化和配置计算......
  • mosquitto参数
    1、订阅参数1.-c设定‘cleansession’为无效状态,这样一直保持订阅状态,即便是已经失去连接,如果再次连接仍旧能够接收的断开期间发送的消息。2.-d打印debug信息3.-h指定要连接的域名默认为localhost4.-i指定clientId5.-I指定clientId前缀6.-kkeepalive每隔一段时间,......
  • jdbc 报错 - 索引中丢失 IN 或 OUT 参数:
    jdbc报错-索引中丢失 IN或OUT参数:通常产生这种异常,是因为语句参数类型不一致所导致,如preparedStatement中的参数本应该是int/integer类型,但是设置参数是setString(1,String.valueof(xxx));或是现在流行的hibernate和ibatis的参数类型配置有问题,Integer配置为varchar2了。......
  • DyLoRA:使用动态无搜索低秩适应的预训练模型的参数有效微调
    又一个针对LoRA的改进方法:DyLoRA:Parameter-EfficientTuningofPretrainedModelsusingDynamicSearch-FreeLowRankAdaptationhttps://arxiv.org/pdf/2210.07558v2.pdfhttps://github.com/huawei-noah/KD-NLP/tree/main/DyLoRAPart1前言LoRA存在的问题:rank的值是固......
  • 【调试】Valgrind内存泄漏内存越界|运行时间|调用|cache命中率|多线程竞态|堆栈分析..
    目录即看即用详细简介Valgrind工具详解安装使用检测内存泄漏其他内存问题memcheck工具的常用选型其他选项附录其他类似工具实例分析:03.使用未初始化的内存04.使用野指针05.动态内存越界访问06.分配空间后没有释放07.不匹配使用delete或者free08.两次......
  • Feign传递参数
    传递单个参数1客户端@RequestMapping("/one")publicBaseRespone(@RequestParam("id")Integerid);服务端@RequestMapping("/one")publicBaseRespone(@RequestParam("id")Integerid){returnnewBaseRe......
  • Android之调用service的方法
    MainActivity.java:privateBackgroundMusicServicecaller;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){Intentsvc=newIntent(getApplicationContext(),BackgroundMusicService.class);if(Build.VERSION.SDK_INT>=Build.VERSIO......
  • memcached命令行参数说明
    评:1、启动Memcache常用参数-p<num>设置TCP端口号(默认不设置为:11211)-U<num>UDP监听端口(默认:11211,0时关闭)[u][b]-l<ip_addr>绑定地址(默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问)[/b][/u]-d以daemon方式运行......
  • MyBatis排序时施用orderby动态参数时需要注意,用$而不是#
    评:mybatis排序时使用orderby动态参数时需要注意,用$而不是#默认情况下,使用#{}格式的语法会导致mybatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法,有时你只是想直接在sql语句中插入一个不改变的字符串。比如,像orderby,你可以这样来使用......