MIT6S081-Lab2总结

大家好,我叫徐锦桐,个人博客地址为www.xujintong.com,github地址为https://github.com/xjintong。平时记录一下学习计算机过程中获取的知识,还有日常折腾的经验,欢迎大家访问。

Lab2就是了解一下xv6的系统调用流程,熟悉一下系统调用过程中的结构啥的。

一、xv6系统调用流程

tarce系统调用为例

1、在用户态的user.h中加入对应加入对应系统调用的跳板函数

2、在user/usys.pl中加入对应的entry()

这个entry()是从用户态到内核态的一个关键,它的宏定义展开代码为:

entry的具体宏展开是:
sub entry {
    my $name = shift;
    print ".global $name\n";
    print "${name}:\n";
    print " li a7, SYS_${name}\n";
    print " ecall\n";
    print " ret\n";
}

# 经过compiler后, entry("trace")为我们在usys.S里生成了如下的汇编代码

# usys.S
.global trace
trace:
 li a7, SYS_trace
 ecall
 ret

通过上述代码可以看出来,entry将对应系统调用的调用号(SYS_trace )加入到a7寄存器中,然后通过ecall(risc-v汇编的系统调用指令)从用户态进入内核态。

3、之后首先会跳到kernel/syscall.c中的syscall函数。

系统调用号(SYS_trace--就是个宏定义)从a7 寄存器中获取,然后通过这个号调用对应的系统调用函数,返回值存在a0寄存器中。

4、通过系统调用号找到对应的系统调用函数

c 复制代码
static uint64 (*syscalls[])(void) = {
[SYS_fork]    sys_fork,
[SYS_exit]    sys_exit,
[SYS_wait]    sys_wait,
[SYS_pipe]    sys_pipe,
[SYS_read]    sys_read,
[SYS_kill]    sys_kill,
[SYS_exec]    sys_exec,
[SYS_fstat]   sys_fstat,
[SYS_chdir]   sys_chdir,
[SYS_dup]     sys_dup,
[SYS_getpid]  sys_getpid,
[SYS_sbrk]    sys_sbrk,
[SYS_sleep]   sys_sleep,
[SYS_uptime]  sys_uptime,
[SYS_open]    sys_open,
[SYS_write]   sys_write,
[SYS_mknod]   sys_mknod,
[SYS_unlink]  sys_unlink,
[SYS_link]    sys_link,
[SYS_mkdir]   sys_mkdir,
[SYS_close]   sys_close,
[SYS_trace]   sys_trace,
[SYS_sysinfo] sys_sysinfo,
};

其实就是个数组,每个数组存着对应的系统调用函数指针。像SYS_fork、SYS_exit这些,其实就是一个宏定义,定义的编号,具体源码如下:

c 复制代码
// System call numbers
#define SYS_fork    1
#define SYS_exit    2
#define SYS_wait    3
#define SYS_pipe    4
#define SYS_read    5
#define SYS_kill    6
#define SYS_exec    7
#define SYS_fstat   8
#define SYS_chdir   9
#define SYS_dup    10
#define SYS_getpid 11
#define SYS_sbrk   12
#define SYS_sleep  13
#define SYS_uptime 14
#define SYS_open   15
#define SYS_write  16
#define SYS_mknod  17
#define SYS_unlink 18
#define SYS_link   19
#define SYS_mkdir  20
#define SYS_close  21
#define SYS_trace  22
#define SYS_sysinfo 23

具体的系统调用的函数实现放在了各个文件中,这里是个extern函数。

比如说,sys_trace放在kernel/sysproc.c文件中,sys_read放在kernel/sysfile.c文件中。

二、将内核态数据复制到用户态

应为内核态和用户态是隔离的,它俩拥有不用的地址空间、寄存器。所以获取系统调用用户态传入的参数我们需要argint()argaddrargstr进行获取。(这三个函数在kernel/syscall.c文件中)

将内核态的数据返回到用户态,这里是用到了copyout函数。具体源码如下:

c 复制代码
// Copy from kernel to user.
// Copy len bytes from src to virtual address dstva in a given page table.
// Return 0 on success, -1 on error.
/*
 将 len 个字节从 src 复制到给定页表中的虚拟地址 dstva
*/
int
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
{
  uint64 n, va0, pa0;

  while(len > 0){
    va0 = PGROUNDDOWN(dstva);   // 找到虚拟地址对应的虚拟页表起始地址
    pa0 = walkaddr(pagetable, va0);   // 通过虚拟页表找到对应的物理页表起始地址
    if(pa0 == 0)
      return -1;
    n = PGSIZE - (dstva - va0);   // 计算该页表的剩余空间
    // 如果剩余空间大于要拷贝的数据长度,只拷贝数据长度部分
    if(n > len)
      n = len;
    /*
      在物理页表中,以(void *)(pa0 + (dstva - va0))地址开始,将n个字节的src,复制到对应位置
    */
    memmove((void *)(pa0 + (dstva - va0)), src, n); 

    len -= n;
    src += n;
    dstva = va0 + PGSIZE;
  }
  return 0;
}

核心就是通过虚拟地址找到对应变量的物理地址,然后直接复制到的物理地址上面。

流程:

  • 1、找到虚拟地址对应的虚拟页表起始地址。

  • 2、通过虚拟页表找到对应的物理页表起始地址

  • 3、如果剩余空间大于要拷贝的数据长度,只拷贝数据长度部分

  • 4、在物理页表中,以(void *)(pa0 + (dstva - va0))地址开始,将n个字节的src,复制到对应位置

三、杂

内核态的头文件

内核态的函数声明都在kernel/defs.h头文件中。

一些结构

kernel/proc.c中定义了一个

c 复制代码
struct proc proc[NPROC];

存着当前所有进程的proc结构。

每个进程都对应一个proc结构,该结构存储着该进程的信息,运行状态,进程名字,pid号等等。

相关推荐
雷神乐乐1 个月前
JavaSE——Arrays类、System类
java·system·arrays
tekin2 个月前
macos 系统文件操作时提示 Read-only file system 解决方法
macos·system·mount·file·解决方法·只读文件系统
一丝晨光4 个月前
ios CCNSDate.m
ios·objective-c·cocoa·软件开发·system·date·string
仁者乐于水4 个月前
Oracle 字符集 简体中文 转换 UTF8
oracle·database·system·character
放羊的牧码5 个月前
Java - 别在 Java 代码里乱打日志了,项目中这样打印日志才足够优雅!
java·logback·日志·slf4j·system·log·优雅
LunarCod5 个月前
这才是计科之 Onix & XV6 源码分析(3、Unix-like系统的进程调度模块)
c++·操作系统·c·unix·xv6·进程调度·onix
Bazinga bingo6 个月前
【Linux】谨慎使用system函数以及对应解决方案
linux·运维·服务器·system
碰碰狗7 个月前
Lab1: Xv6 and Unix utilities
操作系统·xv6
QQQ_7 个月前
MIT6.828实验:Xv6 and Unix utilities
c语言·c++·操作系统·unix·xv6·mit6.828
goodcitizen7 个月前
[apue] 进程控制那些事儿
exec·system·fork·time·clone·vfork·getconf·waitpid·zgrep·waittid·getrusage·times·lastcomm·sa·dump-acct·accton·setuid·seteuid·setreuid