https://pdos.csail.mit.edu/6.S081/2020/labs/syscall.html
Makefile
$U/_trace\
user/user.h
int trace(int);
user/usys.pl
entry("trace");
kernel/syscall.h
#define SYS_trace 22
kernel/sysproc.c
uint64
sys_trace(void)
{
int mask;
if(argint(0, &mask) < 0)
return -1;
myproc()->mask = mask;
return 0;
}
kernerl/syscall.c
void
syscall(void)
{
int num;
struct proc *p = myproc();
int total = NELEM(syscalls);
num = p->trapframe->a7;
if(num > 0 && num < total && 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;
}
int mask = p->mask;
int flag[32];
for (int i = 1; i < 31; i++) {
flag[i] = ((mask >> i) & 0x01);
}
if (flag[num]) {
printf("%d: syscall %s -> %d\n", p->pid, syscall_id_2_name[num], p->trapframe->a0);
}
}
kernel/proc.c 在fork()函数,release()函数被调用之前,添加如下内容。
np->mask = p->mask;
kernel/proc.h(该文件proc结构体的最后一行,添加如下字段)
int mask;
Makefile
$U/_sysinfotest\
user/user.h
struct sysinfo;
int sysinfo(struct sysinfo *);
user/usys.pl
entry("sysinfo");
kernel/syscall.h
#define SYS_sysinfo 23
defs.h
// proc.c
uint64 getnfreeproc(void);
// kalloc.c
uint64 knfreemem();
sysproc.c
uint64
sys_sysinfo(void)
{
uint64 dist; // user pointer to struct stat
if(argaddr(0, &dist) < 0)
return -1;
struct sysinfo info;
info.freemem = knfreemem();
info.nproc = getnfreeproc();
struct proc *p = myproc();
if(copyout(p->pagetable, dist, (char *)&info, sizeof(info)) < 0) {
return -1;
}
return 0;
}
kalloc.c
uint64
knfreemem()
{
int page_cnt = 0;
acquire(&kmem.lock);
struct run *r;
r = kmem.freelist;
while (r) {
page_cnt++;
r = r->next;
}
release(&kmem.lock);
return page_cnt * PGSIZE;
}
proc.c
uint64
getnfreeproc(void)
{
int cnt = 0;
struct proc *p;
for(p = proc; p < &proc[NPROC]; p++) {
acquire(&p->lock);
if(p->state != UNUSED) {
cnt++;
}
release(&p->lock);
}
return cnt;
}
在看源码的过程中,文件kerner/syscall.c文件中,发现如下形式的代码。因为是第一次看这种写法的代码,因此这里记录一下。请看下面代码中syscalls数组,该数组的每个元素为一个函数指针(该函数形参为void,返回值为uint64)。但是每个元素在定义的时候,可以指定其顺序,例如,函数sys_fork指定下标为1(SYS_fork是一个宏变量,值为1,通过[SYS_fork]这种形式,将函数sys_fork的下标设为1),
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,
};
下面笔者自己写了一些测试。
#include
void sum(void) {
printf("sum\n");
}
void sub(void) {
printf("sub\n");
}
void div(void) {
printf("div\n");
}
int test_func() {
void (*func[])(void) = {
[1] sum,
[3] sub,
[2] div,
};
for (int i = 1; i <= 3; i++) {
func[i](); // result: sum, div, sub
}
printf("func size: %d\n", sizeof(func)/(sizeof((func)[0]))); // func size: 4
// func[0](); // segmentfault
// func[4](); // segmentfault
return 0;
}
int test_array() {
int a[] = {
[1] 1,
[3] 3,
[2] 2,
[8] 8,
};
for (int i = 1; i <= 3; i++) {
printf("%d\n", a[i]); // result: 1, 2, 3
}
printf("array size: %d\n", sizeof(a)/sizeof((a)[0])); // array size: 9
return 0;
}
int main() {
test_func();
test_array();
return 0;
}
extern keyword! Extends function’s visibility to all files in the program.https://github.com/aerfalwl/mit-xv6-labs-2020.git