Lab2: system calls

Using gdb

Looking at the backtrace output, which function called syscall?

可以看到是trap.c中usertrap函数调用了syscall函数

What is the value of p->trapframe->a7 and what does that value represent? 

p->trapframe->a7的值为7,代表了函数sys_exec在数组syscalls中的索引值

What was the previous mode that the CPU was in?

sstatus值为0x22,翻译成二进制是100010,第8位SPP为0

说明进入supervisor mode之前是user mode

Write down the assembly instruction the kernel is panicing at. Which register corresponds to the variable num?

可以看到num对应于a3寄存器

Why does the kernel crash? Hint: look at figure 3-3 in the text; is address 0 mapped in the kernel address space? Is that confirmed by the value in scause above?

scause的值为0x0d,也就是十进制13,表示Load page fault

在RISC-V中有效地址从0x80000000开始,地址0x0是无效的

What is the name of the binary that was running when the kernel paniced? What is its process id (pid)? 

System call tracing

proc.h

//proc.h
struct proc
{
	struct spinlock lock;

	// p->lock must be held when using these:
	enum procstate state; // Process state
	void *chan;			  // If non-zero, sleeping on chan
	int killed;			  // If non-zero, have been killed
	int xstate;			  // Exit status to be returned to parent's wait
	int pid;			  // Process ID

	// wait_lock must be held when using this:
	struct proc *parent; // Parent process

	// these are private to the process, so p->lock need not be held.
	uint64 kstack;				 // Virtual address of kernel stack
	uint64 sz;					 // Size of process memory (bytes)
	pagetable_t pagetable;		 // User page table
	struct trapframe *trapframe; // data page for trampoline.S
	struct context context;		 // swtch() here to run process
	struct file *ofile[NOFILE];	 // Open files
	struct inode *cwd;			 // Current directory
	char name[16];				 // Process name (debugging)
	uint32 tracemask;			 //mask for syscall trace
};

proc.c

static struct proc * allocproc(void)
{
	struct proc *p;

	for (p = proc; p < &proc[NPROC]; p++)
	{
		acquire(&p->lock);
		if (p->state == UNUSED)
		{
			goto found;
		}
		else
		{
			release(&p->lock);
		}
	}
	return 0;

found:
	p->pid = allocpid();
	p->state = USED;
	p->tracemask = 0U;

	// Allocate a trapframe page.
	if ((p->trapframe = (struct trapframe *)kalloc()) == 0)
	{
		freeproc(p);
		release(&p->lock);
		return 0;
	}

	// An empty user page table.
	p->pagetable = proc_pagetable(p);
	if (p->pagetable == 0)
	{
		freeproc(p);
		release(&p->lock);
		return 0;
	}

	// Set up new context to start executing at forkret,
	// which returns to user space.
	memset(&p->context, 0, sizeof(p->context));
	p->context.ra = (uint64)forkret;
	p->context.sp = p->kstack + PGSIZE;

	return p;
}

int fork(void)
{
	int i, pid;
	struct proc *np;
	struct proc *p = myproc();

	// Allocate process.
	if ((np = allocproc()) == 0)
	{
		return -1;
	}

	// Copy user memory from parent to child.
	if (uvmcopy(p->pagetable, np->pagetable, p->sz) < 0)
	{
		freeproc(np);
		release(&np->lock);
		return -1;
	}
	np->sz = p->sz;
	np->tracemask = p->tracemask;

	// copy saved user registers.
	*(np->trapframe) = *(p->trapframe);

	// Cause fork to return 0 in the child.
	np->trapframe->a0 = 0;

	// increment reference counts on open file descriptors.
	for (i = 0; i < NOFILE; i++)
		if (p->ofile[i])
			np->ofile[i] = filedup(p->ofile[i]);
	np->cwd = idup(p->cwd);

	safestrcpy(np->name, p->name, sizeof(p->name));

	pid = np->pid;

	release(&np->lock);

	acquire(&wait_lock);
	np->parent = p;
	release(&wait_lock);

	acquire(&np->lock);
	np->state = RUNNABLE;
	release(&np->lock);

	return pid;
}

syscall.h

#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

syscall.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
};

static char *sysnames[] = {
	[SYS_fork] "fork",
	[SYS_exit] "exit",
	[SYS_wait] "wait",
	[SYS_pipe] "pipe",
	[SYS_read] "read",
	[SYS_kill] "kill",
	[SYS_exec] "exec",
	[SYS_fstat] "fstat",
	[SYS_chdir] "chdir",
	[SYS_dup] "dup",
	[SYS_getpid] "getpid",
	[SYS_sbrk] "sbrk",
	[SYS_sleep] "sleep",
	[SYS_uptime] "uptime",
	[SYS_open] "open",
	[SYS_write] "write",
	[SYS_mknod] "mknod",
	[SYS_unlink] "unlink",
	[SYS_link] "link",
	[SYS_mkdir] "mkdir",
	[SYS_close] "close",
	[SYS_trace] "trace"
};

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]();

		if ((p->tracemask >> num) & 1U)
		{
			printf("%d: syscall %s -> %d\n", p->pid, sysnames[num], p->trapframe->a0);
		}
	}
	else
	{
		printf("%d %s: unknown sys call %d\n",
			   p->pid, p->name, num);
		p->trapframe->a0 = -1;
	}
}

sysproc.c

uint64 sys_trace(void)
{
	int n;
	struct proc *p;

	argint(0, &n); 
	p = myproc();
	p->tracemask = (uint32)n;

	return 0;
}

user.h

// system calls
int fork(void);
int exit(int) __attribute__((noreturn));
int wait(int*);
int pipe(int*);
int write(int, const void*, int);
int read(int, void*, int);
int close(int);
int kill(int);
int exec(const char*, char**);
int open(const char*, int);
int mknod(const char*, short, short);
int unlink(const char*);
int fstat(int fd, struct stat*);
int link(const char*, const char*);
int mkdir(const char*);
int chdir(const char*);
int dup(int);
int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);
int trace(int);

usys.pl

entry("fork");
entry("exit");
entry("wait");
entry("pipe");
entry("read");
entry("write");
entry("close");
entry("kill");
entry("exec");
entry("open");
entry("mknod");
entry("unlink");
entry("fstat");
entry("link");
entry("mkdir");
entry("chdir");
entry("dup");
entry("getpid");
entry("sbrk");
entry("sleep");
entry("uptime");
entry("trace");

Makefile

UPROGS=\
	$U/_cat\
	$U/_echo\
	$U/_forktest\
	$U/_grep\
	$U/_init\
	$U/_kill\
	$U/_ln\
	$U/_ls\
	$U/_mkdir\
	$U/_rm\
	$U/_sh\
	$U/_stressfs\
	$U/_usertests\
	$U/_grind\
	$U/_wc\
	$U/_zombie\
	$U/_trace

Sysinfo

其他文件的修改同System call tracing

kalloc.c

int cntfreemem(void)
{
	int cnt = 0;

	for (struct run * p = kmem.freelist; p != 0; p = p->next)
	{
		cnt += PGSIZE;
	}
	
	return cnt;
}

proc.c

int cntproc(void)
{
	int cnt = 0;

	for (int i = 0; i < NPROC; i++)
	{
		if (proc[i].state != UNUSED) 
		{
			cnt++;
		}
	}
	
	return cnt;
}

sysproc.c

uint64 sys_sysinfo(void)
{
	uint64 addr;
	struct proc *p;
	struct sysinfo info;

	argaddr(0, &addr);

	p = myproc();

	info.freemem = cntfreemem();
	info.nproc = cntproc();

	if (copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0)
	{
		return -1;
	}
	
	return 0;
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值