当前位置: 首页 > news >正文

MIT6S081-Lab2总结

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

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

一、xv6系统调用流程

tarce系统调用为例

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

image-20231206141549969

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

image-20231206141753130

这个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_traceecallret

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

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

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

image-20231206142355776

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

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这些,其实就是一个宏定义,定义的编号,具体源码如下:

// 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文件中。

image-20231206143328256

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

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

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

// 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头文件中。

image-20231206143652669

一些结构

kernel/proc.c中定义了一个

struct proc proc[NPROC];

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

image-20231206150341027

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

image-20231206150507722

http://www.lryc.cn/news/254316.html

相关文章:

  • CMMI5大成熟度等级和4大过程域
  • c++新经典模板与泛型编程:const修饰符的移除与增加
  • AUTOSAR汽车电子嵌入式编程精讲300篇-基于加密算法的车载CAN总线安全通信
  • 4-Docker命令之docker start
  • AWS Remote Control ( Wi-Fi ) on i.MX RT1060 EVK - 2 “架构 AWS”
  • 日志框架梳理(Log4j,Reload4j,JUL,JCL,SLF4J,Logback,Log4j2)
  • 内核无锁队列kfifo
  • 18、XSS——cookie安全
  • 从零开发短视频电商 Jmeter压测示例模板详解(无认证场景)
  • C++可以函数重载而C不可以的原因
  • Spark常见算子汇总
  • 【华为数据之道学习笔记】3-1 基于数据特性的分类管理框架
  • 电脑版便签软件怎么设置在桌面上显示?
  • 【华为数据之道学习笔记】2-建立企业级数据综合治理体系
  • 【IC前端虚拟项目】git和svn项目托管平台的简单使用说明
  • C++ IO库
  • Springboot 项目关于版本升级到 3.x ,JDK升级到17的相关问题
  • QGraphicsView实现简易地图7『异步加载-多瓦片-无底图』
  • Spring Boot学习(三十三):集成kafka
  • MOSFET
  • DriveWorks——参数化设计非标定制利器
  • DevEco Studio集成ArkUI-X
  • 网络视频服务器的作用是什么?
  • 解决vue3使用iconpark控制台预警提示问题
  • VMware 虚拟机 NAT 模式网络配置
  • 5-redis高级-哨兵
  • 鸿蒙HarmonyOS4.0开发应用学习笔记
  • 联通宽带+老毛子Padavan固件 开启IP v6
  • 唯创知音WT2003Hx系列单片机语音芯片:家庭理疗产品的智能声音伴侣
  • 2023_Spark_实验二十七:Linux中Crontab(定时任务)命令详解及使用教程