Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8de6f45af1 | ||
|
|
dc9153fcb9 | ||
|
|
4d7493893d | ||
|
|
0c477a6c84 | ||
|
|
7d47335b4f |
5
Makefile
5
Makefile
@ -188,6 +188,11 @@ UPROGS=\
|
||||
$U/_grind\
|
||||
$U/_wc\
|
||||
$U/_zombie\
|
||||
$U/_sleep\
|
||||
$U/_pingpong\
|
||||
$U/_primes\
|
||||
$U/_find\
|
||||
$U/_xargs\
|
||||
|
||||
|
||||
|
||||
|
||||
36
README
36
README
@ -6,7 +6,7 @@ ACKNOWLEDGMENTS
|
||||
|
||||
xv6 is inspired by John Lions's Commentary on UNIX 6th Edition (Peer
|
||||
to Peer Communications; ISBN: 1-57398-013-7; 1st edition (June 14,
|
||||
2000)). See also https://pdos.csail.mit.edu/6.1810/, which provides
|
||||
2000)). See also https://pdos.csail.mit.edu/6.828/, which provides
|
||||
pointers to on-line resources for v6.
|
||||
|
||||
The following people have made contributions: Russ Cox (context switching,
|
||||
@ -14,31 +14,29 @@ locking), Cliff Frey (MP), Xiao Yu (MP), Nickolai Zeldovich, and Austin
|
||||
Clements.
|
||||
|
||||
We are also grateful for the bug reports and patches contributed by
|
||||
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, carlclone, Ian
|
||||
Chen, Dan Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi,
|
||||
eyalz800, Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel
|
||||
Filardo, flespark, Peter Froehlich, Yakir Goaron, Shivam Handa, Matt
|
||||
Harvey, Bryan Henry, jaichenhengjie, Jim Huang, Matúš Jókay, John
|
||||
Jolly, Alexander Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller,
|
||||
Jungwoo Kim, Jonathan Kimmitt, Eddie Kohler, Vadim Kolontsov, Austin
|
||||
Liew, l0stman, Pavan Maddamsetti, Imbar Marinescu, Yandong Mao, Matan
|
||||
Shabtay, Hitoshi Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel
|
||||
Nider, Hayato Ohhashi, OptimisticSide, Harry Porter, Greg Price, Jude
|
||||
Rich, segfault, Ayan Shafqat, Eldar Sehayek, Yongming Shen, Fumiya
|
||||
Shigemitsu, Cam Tenny, tyfkda, Warren Toomey, Stephen Tu, Rafael Ubal,
|
||||
Amane Uehara, Pablo Ventura, Xi Wang, WaheedHafez, Keiichi Watanabe,
|
||||
Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng,
|
||||
ZhUyU1997, and Zou Chang Wei.
|
||||
|
||||
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, Ian Chen, Dan
|
||||
Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi, eyalz800, Nelson
|
||||
Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel Filardo, flespark,
|
||||
Peter Froehlich, Yakir Goaron, Shivam Handa, Matt Harvey, Bryan Henry,
|
||||
jaichenhengjie, Jim Huang, Matúš Jókay, Alexander Kapshuk, Anders
|
||||
Kaseorg, kehao95, Wolfgang Keller, Jungwoo Kim, Jonathan Kimmitt,
|
||||
Eddie Kohler, Vadim Kolontsov, Austin Liew, l0stman, Pavan
|
||||
Maddamsetti, Imbar Marinescu, Yandong Mao, Matan Shabtay, Hitoshi
|
||||
Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel Nider,
|
||||
OptimisticSide, Greg Price, Jude Rich, Ayan Shafqat, Eldar Sehayek,
|
||||
Yongming Shen, Fumiya Shigemitsu, Cam Tenny, tyfkda, Warren Toomey,
|
||||
Stephen Tu, Rafael Ubal, Amane Uehara, Pablo Ventura, Xi Wang, Keiichi
|
||||
Watanabe, Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy
|
||||
Zheng, ZhUyU1997, and Zou Chang Wei.
|
||||
|
||||
The code in the files that constitute xv6 is
|
||||
Copyright 2006-2022 Frans Kaashoek, Robert Morris, and Russ Cox.
|
||||
Copyright 2006-2020 Frans Kaashoek, Robert Morris, and Russ Cox.
|
||||
|
||||
ERROR REPORTS
|
||||
|
||||
Please send errors and suggestions to Frans Kaashoek and Robert Morris
|
||||
(kaashoek,rtm@mit.edu). The main purpose of xv6 is as a teaching
|
||||
operating system for MIT's 6.1810, so we are more interested in
|
||||
operating system for MIT's 6.S081, so we are more interested in
|
||||
simplifications and clarifications than new features.
|
||||
|
||||
BUILDING AND RUNNING XV6
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
Q: Which other xv6 system call(s) could be made faster using this shared page? Explain how.
|
||||
A: sys_uptime. Make the global tick in a user access page, and map the address of tick into usyscall.
|
||||
|
||||
Q: Explain the output of vmprint in terms of Fig 3-4 from the text. What does page 0 contain? What is in page 2? When running in user mode, could the process read/write the memory mapped by page 1? What does the third to last page contain?
|
||||
A: Page 0 contains process's text (code).
|
||||
Page 2 is the guard page.
|
||||
Page 1 could be read and write in user mode, due to its PTE_U(1 << 4), PTE_R(1 << 2) and PTE_W(1 << 3) flags being set.
|
||||
The third to last page, aka page 255-511-509, is the usyscall page used in the last task.
|
||||
@ -1 +1 @@
|
||||
LAB=pgtbl
|
||||
LAB=util
|
||||
|
||||
@ -1,78 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
from gradelib import *
|
||||
|
||||
r = Runner(save("xv6.out"))
|
||||
|
||||
PTE_PRINT = """page table 0x0000000087f6e000
|
||||
..0: pte 0x0000000021fda801 pa 0x0000000087f6a000
|
||||
.. ..0: pte 0x0000000021fda401 pa 0x0000000087f69000
|
||||
.. .. ..0: pte 0x0000000021fdac1f pa 0x0000000087f6b000
|
||||
.. .. ..1: pte 0x0000000021fda00f pa 0x0000000087f68000
|
||||
.. .. ..2: pte 0x0000000021fd9c1f pa 0x0000000087f67000
|
||||
..255: pte 0x0000000021fdb401 pa 0x0000000087f6d000
|
||||
.. ..511: pte 0x0000000021fdb001 pa 0x0000000087f6c000
|
||||
.. .. ..509: pte 0x0000000021fdd813 pa 0x0000000087f76000
|
||||
.. .. ..510: pte 0x0000000021fddc07 pa 0x0000000087f77000
|
||||
.. .. ..511: pte 0x0000000020001c0b pa 0x0000000080007000"""
|
||||
|
||||
VAL_RE = "(0x00000000[0-9a-f]+)"
|
||||
INDENT_RE = r"\s*\.\.\s*"
|
||||
INDENT_ESC = "\\\s*\.\.\\\s*"
|
||||
|
||||
@test(0, "pgtbltest")
|
||||
def test_pgtbltest():
|
||||
r.run_qemu(shell_script([
|
||||
'pgtbltest'
|
||||
]), timeout=300)
|
||||
|
||||
@test(10, "pgtbltest: ugetpid", parent=test_pgtbltest)
|
||||
def test_nettest_():
|
||||
r.match('^ugetpid_test: OK$')
|
||||
|
||||
@test(10, "pgtbltest: pgaccess", parent=test_pgtbltest)
|
||||
def test_nettest_():
|
||||
r.match('^pgaccess_test: OK$')
|
||||
|
||||
@test(10, "pte printout")
|
||||
def test_pteprint():
|
||||
first = True
|
||||
r.run_qemu(shell_script([
|
||||
'echo hi'
|
||||
]))
|
||||
r.match('^hi')
|
||||
p = re.compile(VAL_RE)
|
||||
d = re.compile(INDENT_RE)
|
||||
for l in PTE_PRINT.splitlines():
|
||||
l = d.sub(INDENT_ESC, l)
|
||||
l = p.sub(VAL_RE, l)
|
||||
r.match(r'^{}$'.format(l))
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
matches = re.findall(r'^{}$'.format(l), r.qemu.output, re.MULTILINE)
|
||||
assert_equal(len(matches[0]), 2)
|
||||
pa = (int(matches[0][0], 16) >> 10) << 12
|
||||
assert_equal(int(matches[0][1], 16), pa)
|
||||
|
||||
@test(5, "answers-pgtbl.txt")
|
||||
def test_answers():
|
||||
# just a simple sanity check, will be graded manually
|
||||
check_answers("answers-pgtbl.txt")
|
||||
|
||||
@test(0, "usertests")
|
||||
def test_usertests():
|
||||
r.run_qemu(shell_script([
|
||||
'usertests -q'
|
||||
]), timeout=300)
|
||||
|
||||
@test(10, "usertests: all tests", parent=test_usertests)
|
||||
def test_usertests():
|
||||
r.match('^ALL TESTS PASSED$')
|
||||
|
||||
@test(1, "time")
|
||||
def test_time():
|
||||
check_time()
|
||||
|
||||
run_tests()
|
||||
86
grade-lab-util
Executable file
86
grade-lab-util
Executable file
@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
from gradelib import *
|
||||
|
||||
r = Runner(save("xv6.out"))
|
||||
|
||||
@test(5, "sleep, no arguments")
|
||||
def test_sleep_no_args():
|
||||
r.run_qemu(shell_script([
|
||||
'sleep'
|
||||
]))
|
||||
r.match(no=["exec .* failed", "$ sleep\n$"])
|
||||
|
||||
@test(5, "sleep, returns")
|
||||
def test_sleep_no_args():
|
||||
r.run_qemu(shell_script([
|
||||
'sleep',
|
||||
'echo OK'
|
||||
]))
|
||||
r.match('^OK$', no=["exec .* failed", "$ sleep\n$"])
|
||||
|
||||
@test(10, "sleep, makes syscall")
|
||||
def test_sleep():
|
||||
r.run_qemu(shell_script([
|
||||
'sleep 10',
|
||||
'echo FAIL'
|
||||
]), stop_breakpoint('sys_sleep'))
|
||||
r.match('\\$ sleep 10', no=['FAIL'])
|
||||
|
||||
@test(20, "pingpong")
|
||||
def test_pingpong():
|
||||
r.run_qemu(shell_script([
|
||||
'pingpong', 'echo OK'
|
||||
]))
|
||||
r.match('^\\d+: received ping$', '^\\d+: received pong$', '^OK$')
|
||||
|
||||
@test(20, "primes")
|
||||
def test_primes():
|
||||
r.run_qemu(shell_script([
|
||||
'primes', 'echo OK'
|
||||
]))
|
||||
args = ['prime %d' % i for i in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]]
|
||||
args.append('^OK$')
|
||||
r.match(*args)
|
||||
|
||||
@test(10, "find, in current directory")
|
||||
def test_find_curdir():
|
||||
fn = random_str()
|
||||
r.run_qemu(shell_script([
|
||||
'echo > %s' % fn,
|
||||
'find . %s' % fn
|
||||
]))
|
||||
r.match('./%s' % fn)
|
||||
|
||||
@test(10, "find, recursive")
|
||||
def test_find_recursive():
|
||||
needle = random_str()
|
||||
dirs = [random_str() for _ in range(3)]
|
||||
r.run_qemu(shell_script([
|
||||
'mkdir %s' % dirs[0],
|
||||
'echo > %s/%s' % (dirs[0], needle),
|
||||
'mkdir %s/%s' % (dirs[0], dirs[1]),
|
||||
'echo > %s/%s/%s' % (dirs[0], dirs[1], needle),
|
||||
'mkdir %s' % dirs[2],
|
||||
'echo > %s/%s' % (dirs[2], needle),
|
||||
'find . %s' % needle
|
||||
]))
|
||||
r.match('./%s/%s' % (dirs[0], needle),
|
||||
'./%s/%s/%s' % (dirs[0], dirs[1], needle),
|
||||
'./%s/%s' % (dirs[2], needle))
|
||||
|
||||
@test(19, "xargs")
|
||||
def test_xargs():
|
||||
r.run_qemu(shell_script([
|
||||
'sh < xargstest.sh',
|
||||
'echo DONE',
|
||||
], 'DONE'))
|
||||
matches = re.findall("hello", r.qemu.output)
|
||||
assert_equal(len(matches), 3, "Number of appearances of 'hello'")
|
||||
|
||||
@test(1, "time")
|
||||
def test_time():
|
||||
check_time()
|
||||
|
||||
run_tests()
|
||||
@ -173,7 +173,6 @@ uint64 walkaddr(pagetable_t, uint64);
|
||||
int copyout(pagetable_t, uint64, char *, uint64);
|
||||
int copyin(pagetable_t, char *, uint64, uint64);
|
||||
int copyinstr(pagetable_t, char *, uint64, uint64);
|
||||
void vmprint(pagetable_t pagetable);
|
||||
|
||||
// plic.c
|
||||
void plicinit(void);
|
||||
|
||||
@ -128,7 +128,6 @@ exec(char *path, char **argv)
|
||||
p->trapframe->sp = sp; // initial stack pointer
|
||||
proc_freepagetable(oldpagetable, oldsz);
|
||||
|
||||
if (p->pid == 1) vmprint(p->pagetable);
|
||||
return argc; // this ends up in a0, the first argument to main(argc, argv)
|
||||
|
||||
bad:
|
||||
|
||||
@ -25,10 +25,6 @@
|
||||
#define VIRTIO0 0x10001000
|
||||
#define VIRTIO0_IRQ 1
|
||||
|
||||
#ifdef LAB_NET
|
||||
#define E1000_IRQ 33
|
||||
#endif
|
||||
|
||||
// core local interruptor (CLINT), which contains the timer.
|
||||
#define CLINT 0x2000000L
|
||||
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8*(hartid))
|
||||
@ -57,7 +53,7 @@
|
||||
|
||||
// map kernel stacks beneath the trampoline,
|
||||
// each surrounded by invalid guard pages.
|
||||
#define KSTACK(p) (TRAMPOLINE - (p)*2*PGSIZE - 3*PGSIZE)
|
||||
#define KSTACK(p) (TRAMPOLINE - ((p)+1)* 2*PGSIZE)
|
||||
|
||||
// User memory layout.
|
||||
// Address zero first:
|
||||
@ -66,14 +62,6 @@
|
||||
// fixed-size stack
|
||||
// expandable heap
|
||||
// ...
|
||||
// USYSCALL (shared with kernel)
|
||||
// TRAPFRAME (p->trapframe, used by the trampoline)
|
||||
// TRAMPOLINE (the same page as in the kernel)
|
||||
#define TRAPFRAME (TRAMPOLINE - PGSIZE)
|
||||
#ifdef LAB_PGTBL
|
||||
#define USYSCALL (TRAPFRAME - PGSIZE)
|
||||
|
||||
struct usyscall {
|
||||
int pid; // Process ID
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -131,11 +131,6 @@ found:
|
||||
release(&p->lock);
|
||||
return 0;
|
||||
}
|
||||
if ((p->usyscall_page = (uint64)kalloc()) == 0) {
|
||||
freeproc(p);
|
||||
release(&p->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// An empty user page table.
|
||||
p->pagetable = proc_pagetable(p);
|
||||
@ -144,8 +139,7 @@ found:
|
||||
release(&p->lock);
|
||||
return 0;
|
||||
}
|
||||
struct usyscall* usyscall_ptr = (struct usyscall*)p->usyscall_page;
|
||||
usyscall_ptr->pid = p->pid;
|
||||
|
||||
// Set up new context to start executing at forkret,
|
||||
// which returns to user space.
|
||||
memset(&p->context, 0, sizeof(p->context));
|
||||
@ -164,9 +158,6 @@ freeproc(struct proc *p)
|
||||
if(p->trapframe)
|
||||
kfree((void*)p->trapframe);
|
||||
p->trapframe = 0;
|
||||
if(p->usyscall_page)
|
||||
kfree((void*)p->usyscall_page);
|
||||
p->usyscall_page = 0;
|
||||
if(p->pagetable)
|
||||
proc_freepagetable(p->pagetable, p->sz);
|
||||
p->pagetable = 0;
|
||||
@ -211,14 +202,6 @@ proc_pagetable(struct proc *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mappages(pagetable, USYSCALL, PGSIZE,
|
||||
p->usyscall_page, PTE_U | PTE_R) < 0)
|
||||
{
|
||||
uvmunmap(pagetable, USYSCALL, 1, 0);
|
||||
uvmfree(pagetable, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pagetable;
|
||||
}
|
||||
|
||||
@ -229,7 +212,6 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz)
|
||||
{
|
||||
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||
uvmunmap(pagetable, TRAPFRAME, 1, 0);
|
||||
uvmunmap(pagetable, USYSCALL, 1, 0);
|
||||
uvmfree(pagetable, sz);
|
||||
}
|
||||
|
||||
|
||||
@ -99,7 +99,6 @@ struct proc {
|
||||
uint64 kstack; // Virtual address of kernel stack
|
||||
uint64 sz; // Size of process memory (bytes)
|
||||
pagetable_t pagetable; // User page table
|
||||
uint64 usyscall_page; // USYSCALL page phy addr
|
||||
struct trapframe *trapframe; // data page for trampoline.S
|
||||
struct context context; // swtch() here to run process
|
||||
struct file *ofile[NOFILE]; // Open files
|
||||
|
||||
@ -343,7 +343,6 @@ typedef uint64 *pagetable_t; // 512 PTEs
|
||||
#define PTE_W (1L << 2)
|
||||
#define PTE_X (1L << 3)
|
||||
#define PTE_U (1L << 4) // user can access
|
||||
#define PTE_A (1L << 6)
|
||||
|
||||
// shift a physical address to the right place for a PTE.
|
||||
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
|
||||
|
||||
@ -102,13 +102,6 @@ extern uint64 sys_link(void);
|
||||
extern uint64 sys_mkdir(void);
|
||||
extern uint64 sys_close(void);
|
||||
|
||||
#ifdef LAB_NET
|
||||
extern uint64 sys_connect(void);
|
||||
#endif
|
||||
#ifdef LAB_PGTBL
|
||||
extern uint64 sys_pgaccess(void);
|
||||
#endif
|
||||
|
||||
// An array mapping syscall numbers from syscall.h
|
||||
// to the function that handles the system call.
|
||||
static uint64 (*syscalls[])(void) = {
|
||||
@ -133,16 +126,8 @@ static uint64 (*syscalls[])(void) = {
|
||||
[SYS_link] sys_link,
|
||||
[SYS_mkdir] sys_mkdir,
|
||||
[SYS_close] sys_close,
|
||||
#ifdef LAB_NET
|
||||
[SYS_connect] sys_connect,
|
||||
#endif
|
||||
#ifdef LAB_PGTBL
|
||||
[SYS_pgaccess] sys_pgaccess,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
syscall(void)
|
||||
{
|
||||
|
||||
@ -20,14 +20,3 @@
|
||||
#define SYS_link 19
|
||||
#define SYS_mkdir 20
|
||||
#define SYS_close 21
|
||||
|
||||
// System calls for labs
|
||||
#define SYS_trace 22
|
||||
#define SYS_sysinfo 23
|
||||
#define SYS_sigalarm 24
|
||||
#define SYS_sigreturn 25
|
||||
#define SYS_symlink 26
|
||||
#define SYS_mmap 27
|
||||
#define SYS_munmap 28
|
||||
#define SYS_connect 29
|
||||
#define SYS_pgaccess 30
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "types.h"
|
||||
#include "riscv.h"
|
||||
#include "param.h"
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "memlayout.h"
|
||||
#include "spinlock.h"
|
||||
#include "proc.h"
|
||||
@ -54,7 +54,6 @@ sys_sleep(void)
|
||||
int n;
|
||||
uint ticks0;
|
||||
|
||||
|
||||
argint(0, &n);
|
||||
acquire(&tickslock);
|
||||
ticks0 = ticks;
|
||||
@ -69,35 +68,6 @@ sys_sleep(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
#define MAX_ABITS (64)
|
||||
|
||||
int
|
||||
sys_pgaccess(void)
|
||||
{
|
||||
char access_bits[MAX_ABITS / 8] = {0};
|
||||
uint64 base;
|
||||
int pages;
|
||||
uint64 mask;
|
||||
argaddr(0, &base); // void*
|
||||
argint(1, &pages); // int
|
||||
argaddr(2, &mask); // void*
|
||||
if (pages > MAX_ABITS) return -1;
|
||||
acquire(&myproc()->lock);
|
||||
for (int page = 0; page < pages; ++ page) {
|
||||
pte_t* pte = walk(myproc()->pagetable, base + (page << PGSHIFT), 0);
|
||||
if (*pte & PTE_A) {
|
||||
*pte &= ~PTE_A;
|
||||
access_bits[page / 8] |= 1 << (page & 0x7);
|
||||
}
|
||||
}
|
||||
release(&myproc()->lock);
|
||||
copyout(myproc()->pagetable, mask, access_bits, (pages & 0x7) ? (pages >> 3) + 1 : (pages >> 3));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64
|
||||
sys_kill(void)
|
||||
{
|
||||
|
||||
25
kernel/vm.c
25
kernel/vm.c
@ -437,28 +437,3 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void _vmprint(pagetable_t pagetable, int depth)
|
||||
{
|
||||
if (depth == 3)
|
||||
return;
|
||||
for (int i = 0; i < 512; ++i)
|
||||
{
|
||||
pte_t pte = pagetable[i];
|
||||
if (pte & PTE_V)
|
||||
{
|
||||
for (int _i = 0; _i < depth; ++_i)
|
||||
{
|
||||
printf(".. ");
|
||||
}
|
||||
printf("..%d: pte %p pa %p\n", i, pte, PTE2PA(pte));
|
||||
_vmprint((pagetable_t)PTE2PA(pte), depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vmprint(pagetable_t pagetable)
|
||||
{
|
||||
printf("page table %p\n", pagetable);
|
||||
_vmprint(pagetable, 0);
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/fcntl.h"
|
||||
#include "user/user.h"
|
||||
|
||||
char buf[512];
|
||||
@ -33,7 +32,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
for(i = 1; i < argc; i++){
|
||||
if((fd = open(argv[i], O_RDONLY)) < 0){
|
||||
if((fd = open(argv[i], 0)) < 0){
|
||||
fprintf(2, "cat: cannot open %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
74
user/find.c
Normal file
74
user/find.c
Normal file
@ -0,0 +1,74 @@
|
||||
#include "kernel/types.h"
|
||||
#include "user/user.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/fs.h"
|
||||
|
||||
int fmtname(const char *path) {
|
||||
int p;
|
||||
for(p=strlen(path); p >= 0 && *(path + p) != '/'; p--);
|
||||
p++;
|
||||
return p;
|
||||
}
|
||||
|
||||
void find(const char *path, const char* target) {
|
||||
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;
|
||||
}
|
||||
|
||||
switch(st.type){
|
||||
case T_DEVICE:
|
||||
case T_FILE:
|
||||
if (strcmp(path + fmtname(path), target) == 0) {
|
||||
printf("%s\n", path);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_DIR:
|
||||
if (strcmp(path + fmtname(path), target) == 0) {
|
||||
printf("%s\n", path);
|
||||
}
|
||||
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
|
||||
printf("find: path too long\n");
|
||||
break;
|
||||
}
|
||||
strcpy(buf, path);
|
||||
p = buf+strlen(buf);
|
||||
*p++ = '/';
|
||||
while(read(fd, &de, sizeof(de)) == sizeof(de)){
|
||||
if(de.inum == 0)
|
||||
continue;
|
||||
if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
|
||||
continue;
|
||||
memmove(p, de.name, DIRSIZ);
|
||||
p[DIRSIZ] = 0;
|
||||
if(stat(buf, &st) < 0){
|
||||
printf("find: cannot stat %s\n", buf);
|
||||
continue;
|
||||
}
|
||||
find(buf, target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 3) {
|
||||
printf("\x1b[31mInvalid arguments\x1b[0m\n");
|
||||
printf("\x1b[32musage\x1b[0m: find <base directory> <file name to find>\n");
|
||||
exit(0);
|
||||
}
|
||||
find(argv[1], argv[2]);
|
||||
exit(0);
|
||||
}
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/fcntl.h"
|
||||
#include "user/user.h"
|
||||
|
||||
char buf[1024];
|
||||
@ -52,7 +51,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
for(i = 2; i < argc; i++){
|
||||
if((fd = open(argv[i], O_RDONLY)) < 0){
|
||||
if((fd = open(argv[i], 0)) < 0){
|
||||
printf("grep: cannot open %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
#include "kernel/stat.h"
|
||||
#include "user/user.h"
|
||||
#include "kernel/fs.h"
|
||||
#include "kernel/fcntl.h"
|
||||
|
||||
char*
|
||||
fmtname(char *path)
|
||||
@ -31,7 +30,7 @@ ls(char *path)
|
||||
struct dirent de;
|
||||
struct stat st;
|
||||
|
||||
if((fd = open(path, O_RDONLY)) < 0){
|
||||
if((fd = open(path, 0)) < 0){
|
||||
fprintf(2, "ls: cannot open %s\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
#include "kernel/param.h"
|
||||
#include "kernel/fcntl.h"
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/riscv.h"
|
||||
#include "user/user.h"
|
||||
|
||||
void ugetpid_test();
|
||||
void pgaccess_test();
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
ugetpid_test();
|
||||
pgaccess_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
|
||||
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
|
||||
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");
|
||||
}
|
||||
27
user/pingpong.c
Normal file
27
user/pingpong.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "kernel/types.h"
|
||||
#include "user/user.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int p[2]; // hell, read from p[0] and write to p[1] no matter in pa/ch
|
||||
if (pipe(p) == -1) exit(1);
|
||||
uint8 senddata[] = {0xAC};
|
||||
uint8 recvdata[] = {0};
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
// child
|
||||
if (read(p[0], recvdata, 1) != 1) printf("error child read\n");
|
||||
close(p[0]);
|
||||
printf("%d: received ping\n", getpid());
|
||||
if (write(p[1], senddata, 1) != 1) printf("error child write\n");
|
||||
close(p[1]);
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
if (write(p[1], senddata, 1) != 1) printf("error parent write\n");
|
||||
close(p[1]);
|
||||
if (read(p[0], recvdata, 1) != 1) printf("error parent read\n");
|
||||
printf("%d: received pong\n", getpid());
|
||||
close(p[0]);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
51
user/primes.c
Normal file
51
user/primes.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include "kernel/types.h"
|
||||
#include "user/user.h"
|
||||
|
||||
void pipeline(int leftfd) {
|
||||
int pipefd[2];
|
||||
int p; read(leftfd, &p, sizeof(p));
|
||||
printf("prime %d\n", p);
|
||||
int n;
|
||||
int has_right = 0;
|
||||
while (read(leftfd, &n, sizeof(n)) > 0) {
|
||||
if (n % p != 0) {
|
||||
if (!has_right) {
|
||||
has_right = 1;
|
||||
pipe(pipefd);
|
||||
if (fork() == 0) {
|
||||
close(pipefd[1]);
|
||||
pipeline(pipefd[0]);
|
||||
} else {
|
||||
close(pipefd[0]);
|
||||
}
|
||||
}
|
||||
write(pipefd[1], &n, sizeof(n));
|
||||
}
|
||||
}
|
||||
close(leftfd);
|
||||
if (has_right) {
|
||||
close(pipefd[1]);
|
||||
while(wait(0) != -1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int pipefd[2];
|
||||
pipe(pipefd);
|
||||
int pid = fork();
|
||||
if (pid != 0) {
|
||||
close(pipefd[0]); // no need to read in the feeding proc
|
||||
for (int i = 2; i <= 35; ++ i) {
|
||||
write(pipefd[1], &i, sizeof(i));
|
||||
}
|
||||
close(pipefd[1]);
|
||||
while(wait(0) != -1);
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
close(pipefd[1]); // pipeline proc will have its own write pipe
|
||||
pipeline(pipefd[0]);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
17
user/sleep.c
Normal file
17
user/sleep.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include "kernel/types.h"
|
||||
#include "user/user.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
printf("\x1b[31mUnexpected argument\x1b[0m\n");
|
||||
printf("usage: sleep <ticks>\n");
|
||||
exit(0);
|
||||
}
|
||||
int ticks = atoi(argv[1]);
|
||||
int ret = sleep(ticks);
|
||||
if (ret) {
|
||||
printf("\x1b[31mFailed to sleep\x1b[0m\n");
|
||||
exit(-1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
14
user/ulib.c
14
user/ulib.c
@ -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
|
||||
|
||||
@ -22,14 +22,6 @@ int getpid(void);
|
||||
char* sbrk(int);
|
||||
int sleep(int);
|
||||
int uptime(void);
|
||||
#ifdef LAB_NET
|
||||
int connect(uint32, uint16, uint16);
|
||||
#endif
|
||||
#ifdef LAB_PGTBL
|
||||
int pgaccess(void *base, int len, void *mask);
|
||||
// usyscall region
|
||||
int ugetpid(void);
|
||||
#endif
|
||||
|
||||
// ulib.c
|
||||
int stat(const char*, struct stat*);
|
||||
@ -47,4 +39,3 @@ void free(void*);
|
||||
int atoi(const char*);
|
||||
int memcmp(const void *, const void *, uint);
|
||||
void *memcpy(void *, const void *, uint);
|
||||
int statistics(void*, int);
|
||||
|
||||
@ -36,5 +36,3 @@ entry("getpid");
|
||||
entry("sbrk");
|
||||
entry("sleep");
|
||||
entry("uptime");
|
||||
entry("connect");
|
||||
entry("pgaccess");
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/fcntl.h"
|
||||
#include "user/user.h"
|
||||
|
||||
char buf[512];
|
||||
@ -44,7 +43,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
for(i = 1; i < argc; i++){
|
||||
if((fd = open(argv[i], O_RDONLY)) < 0){
|
||||
if((fd = open(argv[i], 0)) < 0){
|
||||
printf("wc: cannot open %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
59
user/xargs.c
Normal file
59
user/xargs.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include "kernel/param.h"
|
||||
#include "kernel/types.h"
|
||||
#include "user/user.h"
|
||||
|
||||
static inline int is_ws(const char ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int STDIN = 0;
|
||||
char linebuf[1024];
|
||||
char* p = linebuf;
|
||||
char* _argv[MAXARG];
|
||||
while (read(STDIN, p, 1) > 0) {
|
||||
if (*p == '\n') {
|
||||
int i;
|
||||
int in_ws = 1;
|
||||
for (i = 0; i < argc - 1; ++i) {
|
||||
_argv[i] = argv[i + 1];
|
||||
}
|
||||
for (char* p0 = linebuf; p0 <= p; ++p0) {
|
||||
if (is_ws(*p0)) {
|
||||
if (!in_ws) {
|
||||
in_ws = 1;
|
||||
i++;
|
||||
}
|
||||
*p0 = '\0';
|
||||
} else if (in_ws) {
|
||||
in_ws = 0;
|
||||
_argv[i] = p0;
|
||||
}
|
||||
if (i >= MAXARG) {
|
||||
printf("warning: too many arguments");
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
_argv[i] = 0;
|
||||
// for (int j = 0; j < i; ++ j) {
|
||||
// printf("%s\n", _argv[j]);
|
||||
// }
|
||||
if (fork() == 0) {
|
||||
exec(_argv[0], _argv);
|
||||
exit(0);
|
||||
} else {
|
||||
p = linebuf;
|
||||
while (wait(0) != -1)
|
||||
;
|
||||
}
|
||||
} else {
|
||||
p++;
|
||||
if (p >= linebuf + sizeof(linebuf)) {
|
||||
printf("line buffer exceeded\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
6
user/xargstest.sh
Normal file
6
user/xargstest.sh
Normal file
@ -0,0 +1,6 @@
|
||||
mkdir a
|
||||
echo hello > a/b
|
||||
mkdir c
|
||||
echo hello > c/b
|
||||
echo hello > b
|
||||
find . b | xargs grep hello
|
||||
Loading…
Reference in New Issue
Block a user