trapslab initialized

This commit is contained in:
2025-06-12 10:45:04 +08:00
parent 2a8fad821b
commit 028cf61d61
40 changed files with 366 additions and 3188 deletions

193
user/alarmtest.c Normal file
View File

@@ -0,0 +1,193 @@
//
// test program for the alarm lab.
// you can modify this file for testing,
// but please make sure your kernel
// modifications pass the original
// versions of these tests.
//
#include "kernel/param.h"
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/riscv.h"
#include "user/user.h"
void test0();
void test1();
void test2();
void test3();
void periodic();
void slow_handler();
void dummy_handler();
int
main(int argc, char *argv[])
{
test0();
test1();
test2();
test3();
exit(0);
}
volatile static int count;
void
periodic()
{
count = count + 1;
printf("alarm!\n");
sigreturn();
}
// tests whether the kernel calls
// the alarm handler even a single time.
void
test0()
{
int i;
printf("test0 start\n");
count = 0;
sigalarm(2, periodic);
for(i = 0; i < 1000*500000; i++){
if((i % 1000000) == 0)
write(2, ".", 1);
if(count > 0)
break;
}
sigalarm(0, 0);
if(count > 0){
printf("test0 passed\n");
} else {
printf("\ntest0 failed: the kernel never called the alarm handler\n");
}
}
void __attribute__ ((noinline)) foo(int i, int *j) {
if((i % 2500000) == 0) {
write(2, ".", 1);
}
*j += 1;
}
//
// tests that the kernel calls the handler multiple times.
//
// tests that, when the handler returns, it returns to
// the point in the program where the timer interrupt
// occurred, with all registers holding the same values they
// held when the interrupt occurred.
//
void
test1()
{
int i;
int j;
printf("test1 start\n");
count = 0;
j = 0;
sigalarm(2, periodic);
for(i = 0; i < 500000000; i++){
if(count >= 10)
break;
foo(i, &j);
}
if(count < 10){
printf("\ntest1 failed: too few calls to the handler\n");
} else if(i != j){
// the loop should have called foo() i times, and foo() should
// have incremented j once per call, so j should equal i.
// once possible source of errors is that the handler may
// return somewhere other than where the timer interrupt
// occurred; another is that that registers may not be
// restored correctly, causing i or j or the address ofj
// to get an incorrect value.
printf("\ntest1 failed: foo() executed fewer times than it was called\n");
} else {
printf("test1 passed\n");
}
}
//
// tests that kernel does not allow reentrant alarm calls.
void
test2()
{
int i;
int pid;
int status;
printf("test2 start\n");
if ((pid = fork()) < 0) {
printf("test2: fork failed\n");
}
if (pid == 0) {
count = 0;
sigalarm(2, slow_handler);
for(i = 0; i < 1000*500000; i++){
if((i % 1000000) == 0)
write(2, ".", 1);
if(count > 0)
break;
}
if (count == 0) {
printf("\ntest2 failed: alarm not called\n");
exit(1);
}
exit(0);
}
wait(&status);
if (status == 0) {
printf("test2 passed\n");
}
}
void
slow_handler()
{
count++;
printf("alarm!\n");
if (count > 1) {
printf("test2 failed: alarm handler called more than once\n");
exit(1);
}
for (int i = 0; i < 1000*500000; i++) {
asm volatile("nop"); // avoid compiler optimizing away loop
}
sigalarm(0, 0);
sigreturn();
}
//
// dummy alarm handler; after running immediately uninstall
// itself and finish signal handling
void
dummy_handler()
{
sigalarm(0, 0);
sigreturn();
}
//
// tests that the return from sys_sigreturn() does not
// modify the a0 register
void
test3()
{
uint64 a0;
sigalarm(1, dummy_handler);
printf("test3 start\n");
asm volatile("lui a5, 0");
asm volatile("addi a0, a5, 0xac" : : : "a0");
for(int i = 0; i < 500000000; i++)
;
asm volatile("mv %0, a0" : "=r" (a0) );
if(a0 != 0xac)
printf("test3 failed: register a0 changed\n");
else
printf("test3 passed\n");
}

10
user/bttest.c Normal file
View File

@@ -0,0 +1,10 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
sleep(1);
exit(0);
}

17
user/call.c Normal file
View File

@@ -0,0 +1,17 @@
#include "kernel/param.h"
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int g(int x) {
return x+3;
}
int f(int x) {
return g(x);
}
void main(void) {
printf("%d %d\n", f(8)+1, 13);
exit(0);
}

View File

@@ -1,62 +0,0 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
void
test_dirtypages()
{
printf("dirtypages test starting\n");
// Allocate some pages
char *buf = malloc(32 * 4096); // 32 pages
if(buf == 0) {
printf("malloc failed\n");
exit(1);
}
// Clear dirty bits first by calling dirtypages
unsigned int dbits;
if (dirtypages(buf, 32, &dbits) < 0) {
printf("dirtypages failed\n");
exit(1);
}
printf("Initial dirty bits cleared: 0x%x\n", dbits);
// Write to some pages to make them dirty
buf[0] = 1; // Page 0
buf[4096 * 5] = 1; // Page 5
buf[4096 * 10] = 1; // Page 10
// Check dirty pages
if (dirtypages(buf, 32, &dbits) < 0) {
printf("dirtypages failed\n");
exit(1);
}
printf("Dirty bits after writes: 0x%x\n", dbits);
// Check if the expected pages are marked as dirty
if (dbits & (1 << 0))
printf("Page 0 is dirty (expected)\n");
if (dbits & (1 << 5))
printf("Page 5 is dirty (expected)\n");
if (dbits & (1 << 10))
printf("Page 10 is dirty (expected)\n");
// Check again - dirty bits should be cleared now
if (dirtypages(buf, 32, &dbits) < 0) {
printf("dirtypages failed\n");
exit(1);
}
printf("Dirty bits after clearing: 0x%x (should be 0)\n", dbits);
free(buf);
printf("dirtypages test: OK\n");
}
int
main(int argc, char *argv[])
{
test_dirtypages();
exit(0);
}

View File

@@ -1,98 +0,0 @@
#include "kernel/fs.h"
#include "kernel/stat.h"
#include "kernel/types.h"
#include "user/user.h"
int match_pattern(const char *name, const char *pattern) {
const char *star = 0;
const char *name_ptr = name;
const char *pattern_ptr = pattern;
while (1) {
if (*pattern_ptr == '*') {
star = pattern_ptr++;
name_ptr = name;
continue;
}
if (!*name)
return (!*pattern_ptr || (star && !*++pattern_ptr));
if (*pattern_ptr == '?' || *pattern_ptr == *name) {
pattern_ptr++;
name++;
continue;
}
if (star) {
pattern_ptr = star + 1;
name = ++name_ptr;
continue;
}
return 0;
}
}
void find(char *path, char *pattern) {
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if ((fd = open(path, 0)) < 0) {
fprintf(2, "find: cannot open %s\n", path);
return;
}
if (fstat(fd, &st) < 0) {
fprintf(2, "find: cannot stat %s\n", path);
close(fd);
return;
}
if (st.type != T_DIR) {
fprintf(2, "find: %s is not a directory\n", path);
close(fd);
return;
}
if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) {
fprintf(2, "find: path too long\n");
close(fd);
return;
}
strcpy(buf, path);
p = buf + strlen(buf);
*p++ = '/';
while (read(fd, &de, sizeof(de)) == sizeof(de)) {
if (de.inum == 0 || !strcmp(de.name, ".") || !strcmp(de.name, ".."))
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if (stat(buf, &st) < 0) {
fprintf(2, "find: cannot stat %s\n", buf);
continue;
}
if (st.type == T_DIR) {
find(buf, pattern);
} else if (st.type == T_FILE) {
if (match_pattern(de.name, pattern)) {
fprintf(1, "%s\n", buf);
}
}
}
close(fd);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(2, "Usage: find <path> <pattern>\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}

View File

@@ -1,164 +0,0 @@
#include "kernel/param.h"
#include "kernel/fcntl.h"
#include "kernel/types.h"
#include "kernel/riscv.h"
#include "user/user.h"
#define N (8 * (1 << 20))
void print_pgtbl();
void print_kpgtbl();
void ugetpid_test();
void pgaccess_test();
void superpg_test();
int
main(int argc, char *argv[])
{
print_pgtbl();
ugetpid_test();
print_kpgtbl();
pgaccess_test();
superpg_test();
printf("pgtbltest: all tests succeeded\n");
exit(0);
}
char *testname = "???";
void
err(char *why)
{
printf("pgtbltest: %s failed: %s, pid=%d\n", testname, why, getpid());
exit(1);
}
void
print_pte(uint64 va)
{
pte_t pte = (pte_t) pgpte((void *) va);
printf("va 0x%lx pte 0x%lx pa 0x%lx perm 0x%lx\n", va, pte, PTE2PA(pte), PTE_FLAGS(pte));
}
void
print_pgtbl()
{
printf("print_pgtbl starting\n");
for (uint64 i = 0; i < 10; i++) {
print_pte(i * PGSIZE);
}
uint64 top = MAXVA/PGSIZE;
for (uint64 i = top-10; i < top; i++) {
print_pte(i * PGSIZE);
}
printf("print_pgtbl: OK\n");
}
void
ugetpid_test()
{
int i;
printf("ugetpid_test starting\n");
testname = "ugetpid_test";
for (i = 0; i < 64; i++) {
int ret = fork();
if (ret != 0) {
wait(&ret);
if (ret != 0)
exit(1);
continue;
}
if (getpid() != ugetpid())
err("missmatched PID");
exit(0);
}
printf("ugetpid_test: OK\n");
}
void
print_kpgtbl()
{
printf("print_kpgtbl starting\n");
kpgtbl();
printf("print_kpgtbl: OK\n");
}
void
pgaccess_test()
{
char *buf;
unsigned int abits;
printf("pgaccess_test starting\n");
testname = "pgaccess_test";
buf = malloc(32 * PGSIZE);
if (pgaccess(buf, 32, &abits) < 0)
err("pgaccess failed");
buf[PGSIZE * 1] += 1;
buf[PGSIZE * 2] += 1;
buf[PGSIZE * 30] += 1;
if (pgaccess(buf, 32, &abits) < 0)
err("pgaccess failed");
if (abits != ((1 << 1) | (1 << 2) | (1 << 30)))
err("incorrect access bits set");
free(buf);
printf("pgaccess_test: OK\n");
}
void
supercheck(uint64 s)
{
pte_t last_pte = 0;
for (uint64 p = s; p < s + 512 * PGSIZE; p += PGSIZE) {
pte_t pte = (pte_t) pgpte((void *) p);
if(pte == 0)
err("no pte");
if ((uint64) last_pte != 0 && pte != last_pte) {
err("pte different");
}
if((pte & PTE_V) == 0 || (pte & PTE_R) == 0 || (pte & PTE_W) == 0){
err("pte wrong");
}
last_pte = pte;
}
for(int i = 0; i < 512; i += PGSIZE){
*(int*)(s+i) = i;
}
for(int i = 0; i < 512; i += PGSIZE){
if(*(int*)(s+i) != i)
err("wrong value");
}
}
void
superpg_test()
{
int pid;
printf("superpg_test starting\n");
testname = "superpg_test";
char *end = sbrk(N);
if (end == 0 || end == (char*)0xffffffffffffffff)
err("sbrk failed");
uint64 s = SUPERPGROUNDUP((uint64) end);
supercheck(s);
if((pid = fork()) < 0) {
err("fork");
} else if(pid == 0) {
supercheck(s);
exit(0);
} else {
int status;
wait(&status);
if (status != 0) {
exit(0);
}
}
printf("superpg_test: OK\n");
}

View File

@@ -1,21 +0,0 @@
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char *argv[]) {
int proc_f2s[2], proc_s2f[2];
char buffer[8];
pipe(proc_f2s);
pipe(proc_s2f);
if (fork() == 0) {
read(proc_s2f[0], buffer, 4);
printf("%d: received %s\n", getpid(), buffer);
write(proc_f2s[1], "pong", strlen("pong"));
} else {
write(proc_s2f[1], "ping", strlen("ping"));
read(proc_f2s[0], buffer, 4);
printf("%d: received %s\n", getpid(), buffer);
}
exit(0);
}

View File

@@ -1,61 +0,0 @@
#include "kernel/types.h"
#include "user/user.h"
void redirect(int n, int pd[]) {
close(n);
dup(pd[n]);
close(pd[0]);
close(pd[1]);
}
void primes() {
int previous, next;
int fd[2];
while (read(0, &previous, sizeof(int))) {
printf("prime %d\n", previous);
if (pipe(fd) < 0) {
fprintf(2, "pipe failed\n");
exit(1);
}
if (fork() == 0) {
redirect(1, fd);
while (read(0, &next, sizeof(int))) {
if (next % previous != 0) {
write(1, &next, sizeof(int));
}
}
exit(0);
} else {
close(fd[1]);
redirect(0, fd);
}
}
}
int main(int argc, char *argv[]) {
int fd[2];
if (pipe(fd) < 0) {
fprintf(2, "pipe failed\n");
exit(1);
}
if (fork() == 0) {
redirect(1, fd);
for (int i = 2; i < 36; i++) {
write(1, &i, sizeof(int));
}
exit(0);
} else {
close(fd[1]);
redirect(0, fd);
primes();
}
exit(0);
}

View File

@@ -1,13 +0,0 @@
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(2, "Usage: sleep <time>\n");
exit(1);
}
int time = atoi(argv[1]);
// printf("time: %d\n", time);
sleep(time);
exit(0);
}

View File

@@ -1,21 +0,0 @@
#include "kernel/param.h"
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main() {
struct sysinfo info;
if (sysinfo(&info) < 0) {
printf("sysinfo: failed to retrieve system information\n");
exit(1);
}
printf("System Information:\n");
printf(" Free Memory: %d bytes\n", info.freemem);
printf(" Number of Processes: %d\n", info.nproc);
printf(" Unused Process Slots: %d\n", info.unused_proc_num);
printf(" Load Average: %d / 100 \n", info.load_avg);
exit(0);
}

View File

@@ -1,164 +0,0 @@
#include "kernel/types.h"
#include "kernel/riscv.h"
/*#include "kernel/sysinfo.h"*/
#include "user/user.h"
void
sinfo(struct sysinfo *info) {
if (sysinfo(info) < 0) {
printf("FAIL: sysinfo failed");
exit(1);
}
}
//
// use sbrk() to count how many free physical memory pages there are.
//
int
countfree()
{
uint64 sz0 = (uint64)sbrk(0);
struct sysinfo info;
int n = 0;
while(1){
if((uint64)sbrk(PGSIZE) == 0xffffffffffffffff){
break;
}
n += PGSIZE;
}
sinfo(&info);
if (info.freemem != 0) {
printf("FAIL: there is no free mem, but sysinfo.freemem=%d\n",
info.freemem);
exit(1);
}
sbrk(-((uint64)sbrk(0) - sz0));
return n;
}
void
testmem() {
struct sysinfo info;
uint64 n = countfree();
sinfo(&info);
if (info.freemem!= n) {
printf("FAIL: free mem %d (bytes) instead of %d\n", info.freemem, n);
exit(1);
}
if((uint64)sbrk(PGSIZE) == 0xffffffffffffffff){
printf("sbrk failed");
exit(1);
}
sinfo(&info);
if (info.freemem != n-PGSIZE) {
printf("FAIL: free mem %d (bytes) instead of %d\n", n-PGSIZE, info.freemem);
exit(1);
}
if((uint64)sbrk(-PGSIZE) == 0xffffffffffffffff){
printf("sbrk failed");
exit(1);
}
sinfo(&info);
if (info.freemem != n) {
printf("FAIL: free mem %d (bytes) instead of %d\n", n, info.freemem);
exit(1);
}
}
void
testcall() {
struct sysinfo info;
if (sysinfo(&info) < 0) {
printf("FAIL: sysinfo failed\n");
exit(1);
}
if (sysinfo((struct sysinfo *) 0xeaeb0b5b00002f5e) != 0xffffffffffffffff) {
printf("FAIL: sysinfo succeeded with bad argument\n");
exit(1);
}
}
void testproc() {
struct sysinfo info;
uint64 nproc, unused_proc_num;
int status;
int pid;
sinfo(&info);
nproc = info.nproc;
unused_proc_num = info.unused_proc_num;
pid = fork();
if(pid < 0){
printf("sysinfotest: fork failed\n");
exit(1);
}
if(pid == 0){
sinfo(&info);
if(info.nproc != nproc+1) {
printf("sysinfotest: FAIL nproc is %d instead of %d\n", info.nproc, nproc+1);
exit(1);
}
if(info.unused_proc_num != unused_proc_num-1) {
printf("sysinfotest: FAIL unused_proc_num is %d instead of %d\n", info.unused_proc_num, unused_proc_num-1);
exit(1);
}
exit(0);
}
wait(&status);
sinfo(&info);
if(info.nproc != nproc) {
printf("sysinfotest: FAIL nproc is %d instead of %d\n", info.nproc, nproc);
exit(1);
}
if(info.unused_proc_num != unused_proc_num) {
printf("sysinfotest: FAIL unused_proc_num is %d instead of %d\n", info.unused_proc_num, unused_proc_num);
exit(1);
}
}
void testbad() {
int pid = fork();
int xstatus;
if(pid < 0){
printf("sysinfotest: fork failed\n");
exit(1);
}
if(pid == 0){
sinfo(0x0);
exit(0);
}
wait(&xstatus);
if(xstatus == -1) // kernel killed child?
exit(0);
else {
printf("sysinfotest: testbad succeeded %d\n", xstatus);
exit(xstatus);
}
}
int
main(int argc, char *argv[])
{
printf("sysinfotest: start\n");
testcall();
testmem();
testproc();
printf("sysinfotest: OK\n");
exit(0);
}

View File

@@ -1,24 +0,0 @@
#include "kernel/param.h"
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
int i;
char *nargv[MAXARG];
if(argc < 3 || (argv[1][0] < '0' || argv[1][0] > '9')){
fprintf(2, "Usage: %s mask command\n", argv[0]);
exit(1);
}
if (trace(atoi(argv[1])) < 0) {
fprintf(2, "%s: trace failed\n", argv[0]);
exit(1);
}
for(i = 2; i < argc && i < MAXARG; i++){
nargv[i-2] = argv[i];
}
exec(nargv[0], nargv);
exit(0);
}

View File

@@ -1,13 +1,8 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fcntl.h"
#ifdef LAB_PGTBL
#include "kernel/riscv.h"
#include "kernel/memlayout.h"
#endif
#include "user/user.h"
//
// wrapper so that it's OK if main() does not call exit().
//
@@ -150,12 +145,3 @@ memcpy(void *dst, const void *src, uint n)
{
return memmove(dst, src, n);
}
#ifdef LAB_PGTBL
int
ugetpid(void)
{
struct usyscall *u = (struct usyscall *)USYSCALL;
return u->pid;
}
#endif

View File

@@ -1,15 +0,0 @@
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char *argv[]) {
if (argc != 1) {
// 错误输出到stderr文件描述符2
fprintf(2, "Usage: uptime\n");
exit(1);
}
fprintf(1,"up: %d\n",uptime());
exit(0);
}

View File

@@ -1,12 +1,3 @@
#ifdef LAB_MMAP
typedef unsigned long size_t;
typedef long int off_t;
#endif
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long uint64;
struct stat;
// system calls
@@ -31,19 +22,6 @@ int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);
#ifdef LAB_NET
int bind(uint32);
int unbind(uint32);
int send(uint32, uint32, uint32, char *, uint32);
int recv(uint32, uint32*, uint32*, char *, uint32);
#endif
#ifdef LAB_PGTBL
int ugetpid(void);
uint64 pgpte(void*);
void kpgtbl(void);
int pgaccess(void *base, int len, void *mask);
int dirtypages(void *base, int len, void *mask);
#endif
// ulib.c
int stat(const char*, struct stat*);
@@ -59,9 +37,6 @@ void* memset(void*, int, uint);
int atoi(const char*);
int memcmp(const void *, const void *, uint);
void *memcpy(void *, const void *, uint);
#ifdef LAB_LOCK
int statistics(void*, int);
#endif
// umalloc.c
void* malloc(uint);

View File

@@ -244,7 +244,7 @@ copyinstr3(char *s)
// See if the kernel refuses to read/write user memory that the
// application doesn't have anymore, because it returned it.
void
rwsbrk(char* arg)
rwsbrk(char* argv)
{
int fd, n;
@@ -967,8 +967,6 @@ forkfork(char *s)
enum { N=2 };
for(int i = 0; i < N; i++){
sleep(4);
exit(0);
int pid = fork();
if(pid < 0){
printf("%s: fork failed", s);
@@ -1037,8 +1035,6 @@ forkforkfork(char *s)
void
reparent2(char *s)
{
sleep(3);
exit(0);
for(int i = 0; i < 800; i++){
int pid1 = fork();
if(pid1 < 0){
@@ -2008,7 +2004,6 @@ sbrkbasic(char *s)
char *c, *a, *b;
// does sbrk() return the expected failure value?
exit(0);
pid = fork();
if(pid < 0){
printf("fork failed in sbrkbasic\n");
@@ -2071,7 +2066,6 @@ sbrkmuch(char *s)
enum { BIG=100*1024*1024 };
char *c, *oldbrk, *a, *lastaddr, *p;
uint64 amt;
exit(0);
oldbrk = sbrk(0);
@@ -2186,7 +2180,6 @@ sbrkfail(char *s)
char *c, *a;
int pids[10];
int pid;
exit(0);
if(pipe(fds) != 0){
printf("%s: pipe() failed\n", s);

View File

@@ -36,11 +36,3 @@ entry("getpid");
entry("sbrk");
entry("sleep");
entry("uptime");
entry("bind");
entry("unbind");
entry("send");
entry("recv");
entry("pgpte");
entry("kpgtbl");
entry("pgaccess");
entry("dirtypages");

View File

@@ -1,59 +0,0 @@
#include "kernel/param.h"
#include "kernel/stat.h"
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(2, "Usage: xargs command\n");
exit(1);
}
char *cmd[argc + 1];
int index = 0, data = 0;
for (int i = 1; i < argc; ++i) {
cmd[index++] = argv[i];
}
char buffer[MAXARG];
char line[MAXARG] = {0};
int line_pos = 0;
while ((data = read(0, buffer, MAXARG)) > 0) {
for (int i = 0; i < data; ++i) {
if (buffer[i] == '\n' || buffer[i] == ' ') {
line[line_pos] = 0;
if (line_pos > 0) {
char *arg = malloc(line_pos + 1);
strcpy(arg, line);
cmd[index++] = arg;
}
line_pos = 0;
if (buffer[i] == '\n') {
cmd[index] = 0;
if (fork() == 0) {
exec(cmd[0], cmd);
exit(1);
}
wait(0);
index = argc - 1;
}
} else {
line[line_pos++] = buffer[i];
}
}
}
// bug fixed
if (line_pos > 0) {
line[line_pos] = 0;
cmd[index++] = line;
cmd[index] = 0;
if (fork() == 0) {
exec(cmd[0], cmd);
}
wait(0);
}
exit(0);
}

View File

@@ -1,6 +0,0 @@
mkdir a
echo hello > a/b
mkdir c
echo hello > c/b
echo hello > b
find . b | xargs grep hello