XV6学习(2)Lab syscall
实验的代码放在了Github上。
第二个实验是Lab: system calls。
这个实验主要就是自己实现几个简单的系统调用并添加到XV6中。
XV6系统调用
添加系统调用主要有以下几步:
在user/user.h
中添加系统调用函数的定义。
在user/usys.pl
中添加入口,这个文件将会在make
后生成user/usys.S
文件,在该汇编文件中,每个函数就只有三行,将系统调用号通过li(load imm)存入a7寄存器,之后使用ecall进入内核态,最后返回。
fork:
li a7, SYS_fork
ecall
ret
在kernel/syscall.h
中定义系统调用号。
在kernel/syscall.c
的syscalls
函数指针数组中添加对应的函数。在syscall
函数中,先读取trapframe->a7
获取系统调用号,之后根据该系统调用号查找syscalls
数组中的对应的处理函数并调用。
System call tracing (moderate)
先在proc
结构体中添加一个trace_mask
字段,之后在fork
函数中复制该字段到新进程。
在系统调用sys_trace
中就只要通过argint
函数读取参数,然后设置给trace_mask
字段就行了。
最后修改syscall
,当系统调用号和trace_mask
匹配时就打印相关信息。
// proc.h
struct proc {
...
// this is for sys_trace()
uint trace_mask;
};
// proc.c
int
fork(void) fork(void)
{
...
// copy trace mask
np->trace_mask = p->trace_mask;
...
}
// sysproc.c
uint64
sys_trace(void)
{
uint mask;
if(argint(0, (int*)&mask) < 0)
return -1;
struct proc *p = myproc();
p->trace_mask |= mask;
return 0;
}
// syscall.c
void
syscall(void)
{
int num;
struct proc *p = myproc();
num = p->trapframe->a7;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
uint64 ret = syscalls[num]();
p->trapframe->a0 = ret;
if((1 << num) & p->trace_mask) {
printf("%d: syscall %s -> %d\n", p->pid, syscall_name[num], ret);
}
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}
Sysinfo (moderate)
这一个系统调用主要就是要实现freemem
和nproc
两个函数来统计内存和进程。
// sysproc.c
uint64
sys_sysinfo(void)
{
uint64 info; // user pointer
struct sysinfo kinfo;
struct proc *p = myproc();
if(argaddr(0, &info) < 0){
return -1;
}
kinfo.freemem = freemem();
kinfo.nproc = nproc();
if(copyout(p->pagetable, info, (char*)&kinfo, sizeof(kinfo)) < 0){
return -1;
}
return 0;
}
阅读kalloc
和kfree
两个函数就可以知道,kmem.freelist
是一个保存了当前空闲内存块的链表,因此只需要统计这个链表的长度再乘以PGSIZE
就可以得到空闲内存。
// kalloc.c
uint64
freemem(void)
{
uint64 counter = 0;
struct run *r;
acquire(&kmem.lock);
r = kmem.freelist;
while(r){
r = r->next;
++counter;
}
release(&kmem.lock);
return counter * PGSIZE;
}
阅读procdump
和相关代码就可以知道,XV6的进程结构体保存在proc[NPROC]
数组当中。而proc->state
字段保存了PCB的当前状态,有UNUSED、SLEEPING、RUNNABLE、RUNNING、ZOMBIE五种状态。因此只需要遍历这个数组,然后统计state
不是UNUSED状态的就行了。
// proc.c
uint64
nproc(void)
{
uint64 counter = 0;
struct proc *p;
for(p = proc; p < &proc[NPROC]; p++) {
acquire(&p->lock);
if(p->state != UNUSED) {
++counter;
}
release(&p->lock);
}
return counter;
}
XV6学习(2)Lab syscall的更多相关文章
- XV6学习笔记(2) :内存管理
XV6学习笔记(2) :内存管理 在学习笔记1中,完成了对于pc启动和加载的过程.目前已经可以开始在c语言代码中运行了,而当前已经开启了分页模式,不过是两个4mb的大的内存页,而没有开启小的内存页.接 ...
- xv6学习笔记(3):中断处理和系统调用
xv6学习笔记(3):中断处理和系统调用 1. tvinit函数 这个函数位于main函数内 表明了就是设置idt表 void tvinit(void) { int i; for(i = 0; i & ...
- xv6学习笔记(4) : 进程调度
xv6学习笔记(4) : 进程 xv6所有程序都是单进程.单线程程序.要明白这个概念才好继续往下看 1. XV6中进程相关的数据结构 在XV6中,与进程有关的数据结构如下 // Per-process ...
- xv6学习笔记(5) : 锁与管道与多cpu
xv6学习笔记(5) : 锁与管道与多cpu 1. xv6锁结构 1. xv6操作系统要求在内核临界区操作时中断必须关闭. 如果此时中断开启,那么可能会出现以下死锁情况: 进程A在内核态运行并拿下了p ...
- XV6学习笔记(1) : 启动与加载
XV6学习笔记(1) 1. 启动与加载 首先我们先来分析pc的启动.其实这个都是老生常谈了,但是还是很重要的(也不知道面试官考不考这玩意), 1. 启动的第一件事-bios 首先启动的第一件事就是运行 ...
- XV6学习(1) Lab util
正在学习MIT的6.S081,把做的实验写一写吧. 实验的代码放在了Github上. 第一个实验是Lab util,算是一个热身的实验,没有涉及到系统的底层,就是使用系统调用来完成几个用户模式的小程序 ...
- XV6学习(16)Lab net: Network stack
最后一个实验了,代码在Github上. 这一个实验其实挺简单的,就是要实现网卡的e1000_transmit和e1000_recv函数.不过看以前的实验好像还要实现上层socket相关的代码,今年就只 ...
- XV6学习(9)Lab cow: Copy-on-write fork
代码在github上.总体来说如果理解了COW机制的话,这个实验的完成也没有很复杂. 这一个实验是要完成COW(copy on write)fork.在原始的XV6中,fork函数是通过直接对进程的地 ...
- XV6学习(11)Lab thread: Multithreading
代码放在github上. 这一次实验感觉挺简单的,特别是后面两个小实验.主要就是对多线程和锁进行一个学习. Uthread: switching between threads 这一个实验是要实现一个 ...
随机推荐
- Sharding-JDBC使用jasypt3.0及以上版本加密数据库连接密码
本文中介绍的是基于Sharding-JDBC 4.0和jasypt 3.0及其以上版本对数据库连接密码进行加密操作 引入依赖 项目的pom.xml中引入maven依赖 <dependency&g ...
- 微服务痛点-基于Dubbo + Seata的分布式事务(AT)模式
前言 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata 将为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案. ...
- 爱普生 L4160 Serveies 网络打印机配置(问题解决)
一.爱普生网络打印机固定IP地址 用网络打印机过程中,偶尔会出现打印机脱机的状况,大多数原因是打印机的IP地址在路由器重启过后重新分配了IP地址导致的.此时,为了减少不必要的麻烦就需要固定打印机的IP ...
- 【命令】vmstat命令和pmap命令
博客链接地址:https://www.cnblogs.com/l75790/articles/9197733.html
- 前端技术VUE 的前世今生从PC 走向移动
一.Vue的前世 Vue 框架诞生于2014年,他的作者为中国人–尤雨溪(江苏无锡人).Vue用于构建交互式的Web界面的库,是一个构建数据驱动的Web界面渐进式框架,该框架遵循CMD规范,并且提供的 ...
- MySQL建立索引遵循原则的注意点
1.选择唯一性索引 唯一性索引的数据是唯一的,可以更快的通过该索引查询某条数据. 2.为经常需要排序,分组和联合操作的字段建立索引 order by,group by的字段在排序操作时很是耗时,可以对 ...
- 什么是Cassandra数据库
在本文中,我们将介绍Cassandra名字的含义.Cassandra的发展简史.Cassandra这项技术的特点及优势,以及对于这项技术的未来展望. 本文将用浅显易懂的方式,帮助您将对Cassandr ...
- sql语句查询,limit与order by 同时出现,应该order by在前面
eg:select orderid,status,createtime from orders where appid = :appId and userid = :userId order by c ...
- ceph对接k8s storage class
简介 对接ceph的rbd和cephfs到k8s中提供持久化存储 环境 主机名 IP role 操作系统 ceph-01 172.16.31.11 mon osd CentOS7.8 ceph-02 ...
- Java高并发与多线程(一)-----概念
其实之前一直想专门写一篇,单独说一说Java的多线程与高并发,但是一直以来,都没有想到能够用什么比较有趣的表现形式去表达出来,而且网上充斥着很多类似的博客,有好的又不好的,有简介的有繁琐的,所以也一直 ...