Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8de6f45af1 | ||
|
|
dc9153fcb9 | ||
|
|
4d7493893d | ||
|
|
0c477a6c84 | ||
|
|
7d47335b4f |
16
.vscode/c_cpp_properties.json
vendored
16
.vscode/c_cpp_properties.json
vendored
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Linux",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/**"
|
|
||||||
],
|
|
||||||
"defines": ["LAB_MMAP"],
|
|
||||||
"compilerPath": "/usr/bin/gcc",
|
|
||||||
"cStandard": "gnu17",
|
|
||||||
"cppStandard": "gnu++17",
|
|
||||||
"intelliSenseMode": "linux-gcc-x64"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 4
|
|
||||||
}
|
|
||||||
8
Makefile
8
Makefile
@ -106,7 +106,7 @@ endif
|
|||||||
|
|
||||||
ifdef KCSAN
|
ifdef KCSAN
|
||||||
CFLAGS += -DKCSAN
|
CFLAGS += -DKCSAN
|
||||||
KCSANFLAG = -fsanitize=thread -fno-inline
|
KCSANFLAG = -fsanitize=thread
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Disable PIE when possible (for Ubuntu 16.10 toolchain)
|
# Disable PIE when possible (for Ubuntu 16.10 toolchain)
|
||||||
@ -188,7 +188,11 @@ UPROGS=\
|
|||||||
$U/_grind\
|
$U/_grind\
|
||||||
$U/_wc\
|
$U/_wc\
|
||||||
$U/_zombie\
|
$U/_zombie\
|
||||||
$U/_mmaptest\
|
$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
|
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,
|
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.
|
pointers to on-line resources for v6.
|
||||||
|
|
||||||
The following people have made contributions: Russ Cox (context switching,
|
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.
|
Clements.
|
||||||
|
|
||||||
We are also grateful for the bug reports and patches contributed by
|
We are also grateful for the bug reports and patches contributed by
|
||||||
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, carlclone, Ian
|
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, Ian Chen, Dan
|
||||||
Chen, Dan Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi,
|
Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi, eyalz800, Nelson
|
||||||
eyalz800, Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel
|
Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel Filardo, flespark,
|
||||||
Filardo, flespark, Peter Froehlich, Yakir Goaron, Shivam Handa, Matt
|
Peter Froehlich, Yakir Goaron, Shivam Handa, Matt Harvey, Bryan Henry,
|
||||||
Harvey, Bryan Henry, jaichenhengjie, Jim Huang, Matúš Jókay, John
|
jaichenhengjie, Jim Huang, Matúš Jókay, Alexander Kapshuk, Anders
|
||||||
Jolly, Alexander Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller,
|
Kaseorg, kehao95, Wolfgang Keller, Jungwoo Kim, Jonathan Kimmitt,
|
||||||
Jungwoo Kim, Jonathan Kimmitt, Eddie Kohler, Vadim Kolontsov, Austin
|
Eddie Kohler, Vadim Kolontsov, Austin Liew, l0stman, Pavan
|
||||||
Liew, l0stman, Pavan Maddamsetti, Imbar Marinescu, Yandong Mao, Matan
|
Maddamsetti, Imbar Marinescu, Yandong Mao, Matan Shabtay, Hitoshi
|
||||||
Shabtay, Hitoshi Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel
|
Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel Nider,
|
||||||
Nider, Hayato Ohhashi, OptimisticSide, Harry Porter, Greg Price, Jude
|
OptimisticSide, Greg Price, Jude Rich, Ayan Shafqat, Eldar Sehayek,
|
||||||
Rich, segfault, Ayan Shafqat, Eldar Sehayek, Yongming Shen, Fumiya
|
Yongming Shen, Fumiya Shigemitsu, Cam Tenny, tyfkda, Warren Toomey,
|
||||||
Shigemitsu, Cam Tenny, tyfkda, Warren Toomey, Stephen Tu, Rafael Ubal,
|
Stephen Tu, Rafael Ubal, Amane Uehara, Pablo Ventura, Xi Wang, Keiichi
|
||||||
Amane Uehara, Pablo Ventura, Xi Wang, WaheedHafez, Keiichi Watanabe,
|
Watanabe, Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy
|
||||||
Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng,
|
Zheng, ZhUyU1997, and Zou Chang Wei.
|
||||||
ZhUyU1997, and Zou Chang Wei.
|
|
||||||
|
|
||||||
|
|
||||||
The code in the files that constitute xv6 is
|
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
|
ERROR REPORTS
|
||||||
|
|
||||||
Please send errors and suggestions to Frans Kaashoek and Robert Morris
|
Please send errors and suggestions to Frans Kaashoek and Robert Morris
|
||||||
(kaashoek,rtm@mit.edu). The main purpose of xv6 is as a teaching
|
(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.
|
simplifications and clarifications than new features.
|
||||||
|
|
||||||
BUILDING AND RUNNING XV6
|
BUILDING AND RUNNING XV6
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
LAB=mmap
|
LAB=util
|
||||||
|
|||||||
@ -1,57 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import re
|
|
||||||
from gradelib import *
|
|
||||||
|
|
||||||
r = Runner(save("xv6.out"))
|
|
||||||
|
|
||||||
@test(0, "running mmaptest")
|
|
||||||
def test_mmaptest():
|
|
||||||
r.run_qemu(shell_script([
|
|
||||||
'mmaptest'
|
|
||||||
]), timeout=180)
|
|
||||||
|
|
||||||
@test(20, "mmaptest: mmap f", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_mmap_f():
|
|
||||||
r.match('^test mmap f: OK$')
|
|
||||||
|
|
||||||
@test(10, "mmaptest: mmap private", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_mmap_private():
|
|
||||||
r.match('^test mmap private: OK$')
|
|
||||||
|
|
||||||
@test(10, "mmaptest: mmap read-only", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_mmap_readonly():
|
|
||||||
r.match('^test mmap read-only: OK$')
|
|
||||||
|
|
||||||
@test(10, "mmaptest: mmap read/write", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_mmap_readwrite():
|
|
||||||
r.match('^test mmap read/write: OK$')
|
|
||||||
|
|
||||||
@test(10, "mmaptest: mmap dirty", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_mmap_dirty():
|
|
||||||
r.match('^test mmap dirty: OK$')
|
|
||||||
|
|
||||||
@test(10, "mmaptest: not-mapped unmap", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_mmap_unmap():
|
|
||||||
r.match('^test not-mapped unmap: OK$')
|
|
||||||
|
|
||||||
@test(10, "mmaptest: two files", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_mmap_two():
|
|
||||||
r.match('^test mmap two files: OK$')
|
|
||||||
|
|
||||||
@test(40, "mmaptest: fork_test", parent=test_mmaptest)
|
|
||||||
def test_mmaptest_fork_test():
|
|
||||||
r.match('^fork_test OK$')
|
|
||||||
|
|
||||||
@test(19, "usertests")
|
|
||||||
def test_usertests():
|
|
||||||
r.run_qemu(shell_script([
|
|
||||||
'usertests -q'
|
|
||||||
]), timeout=300)
|
|
||||||
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()
|
||||||
@ -187,6 +187,3 @@ void virtio_disk_intr(void);
|
|||||||
|
|
||||||
// number of elements in fixed-size array
|
// number of elements in fixed-size array
|
||||||
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
|
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
@ -3,13 +3,3 @@
|
|||||||
#define O_RDWR 0x002
|
#define O_RDWR 0x002
|
||||||
#define O_CREATE 0x200
|
#define O_CREATE 0x200
|
||||||
#define O_TRUNC 0x400
|
#define O_TRUNC 0x400
|
||||||
|
|
||||||
#ifdef LAB_MMAP
|
|
||||||
#define PROT_NONE 0x0
|
|
||||||
#define PROT_READ 0x1
|
|
||||||
#define PROT_WRITE 0x2
|
|
||||||
#define PROT_EXEC 0x4
|
|
||||||
|
|
||||||
#define MAP_SHARED 0x01
|
|
||||||
#define MAP_PRIVATE 0x02
|
|
||||||
#endif
|
|
||||||
|
|||||||
171
kernel/proc.c
171
kernel/proc.c
@ -5,15 +5,6 @@
|
|||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "fcntl.h"
|
|
||||||
#include "sleeplock.h"
|
|
||||||
#include "fs.h"
|
|
||||||
#include "file.h"
|
|
||||||
|
|
||||||
static struct vma vma_pool[NMAXVMA];
|
|
||||||
static struct spinlock lock_vma_pool;
|
|
||||||
uint64 do_munmap(uint64 addr, int length);
|
|
||||||
uint64 do_mmap(struct proc* p, int length, int prot, int flags, int fd);
|
|
||||||
|
|
||||||
struct cpu cpus[NCPU];
|
struct cpu cpus[NCPU];
|
||||||
|
|
||||||
@ -42,7 +33,7 @@ void
|
|||||||
proc_mapstacks(pagetable_t kpgtbl)
|
proc_mapstacks(pagetable_t kpgtbl)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
initlock(&lock_vma_pool, "vma_pool");
|
|
||||||
for(p = proc; p < &proc[NPROC]; p++) {
|
for(p = proc; p < &proc[NPROC]; p++) {
|
||||||
char *pa = kalloc();
|
char *pa = kalloc();
|
||||||
if(pa == 0)
|
if(pa == 0)
|
||||||
@ -327,31 +318,6 @@ fork(void)
|
|||||||
np->parent = p;
|
np->parent = p;
|
||||||
release(&wait_lock);
|
release(&wait_lock);
|
||||||
|
|
||||||
acquire(&np->lock);
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
if (p->map_region[i]) {
|
|
||||||
struct vma* newvma = 0;
|
|
||||||
acquire(&lock_vma_pool);
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
if (vma_pool[i].length == 0) {
|
|
||||||
newvma = &vma_pool[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!newvma || newvma->length)
|
|
||||||
panic("mmap: vma pool run out");
|
|
||||||
newvma->f = filedup(p->map_region[i]->f);
|
|
||||||
newvma->addr = p->map_region[i]->addr;
|
|
||||||
newvma->prot = p->map_region[i]->prot;
|
|
||||||
newvma->length = p->map_region[i]->length;
|
|
||||||
newvma->flag = p->map_region[i]->flag;
|
|
||||||
newvma->offset = p->map_region[i]->offset;
|
|
||||||
release(&lock_vma_pool);
|
|
||||||
np->map_region[i] = newvma;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
release(&np->lock);
|
|
||||||
|
|
||||||
acquire(&np->lock);
|
acquire(&np->lock);
|
||||||
np->state = RUNNABLE;
|
np->state = RUNNABLE;
|
||||||
release(&np->lock);
|
release(&np->lock);
|
||||||
@ -385,13 +351,6 @@ exit(int status)
|
|||||||
if(p == initproc)
|
if(p == initproc)
|
||||||
panic("init exiting");
|
panic("init exiting");
|
||||||
|
|
||||||
// clear mmaps
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
if (p->map_region[i]) {
|
|
||||||
do_munmap(p->map_region[i]->addr, p->map_region[i]->length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close all open files.
|
// Close all open files.
|
||||||
for(int fd = 0; fd < NOFILE; fd++){
|
for(int fd = 0; fd < NOFILE; fd++){
|
||||||
if(p->ofile[fd]){
|
if(p->ofile[fd]){
|
||||||
@ -722,131 +681,3 @@ procdump(void)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 do_mmap(struct proc* p, int length, int prot, int flags, int fd)
|
|
||||||
{
|
|
||||||
uint64 addr;
|
|
||||||
struct vma* newvma = 0;
|
|
||||||
if (fd < 0 || fd > NOFILE || p->ofile[fd] == 0){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!p->ofile[fd]->writable && (prot & PROT_WRITE) && (flags != MAP_PRIVATE)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// find vacant addr space
|
|
||||||
addr = MMAP_START;
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
// in case some va has been occupied by some other vma but not accessed
|
|
||||||
if (p->map_region[i]) {
|
|
||||||
int _tmp = PGROUNDUP(p->map_region[i]->addr + length);
|
|
||||||
addr = _tmp > addr ? _tmp : addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
acquire(&lock_vma_pool);
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
if (vma_pool[i].length == 0) {
|
|
||||||
newvma = &vma_pool[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!newvma || newvma->length)
|
|
||||||
panic("mmap: vma pool run out");
|
|
||||||
newvma->f = p->ofile[fd];
|
|
||||||
newvma->addr = addr;
|
|
||||||
newvma->prot = prot;
|
|
||||||
newvma->length = length;
|
|
||||||
newvma->flag = flags;
|
|
||||||
newvma->offset = 0;
|
|
||||||
release(&lock_vma_pool);
|
|
||||||
|
|
||||||
filedup(newvma->f);
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
if (p->map_region[i] == 0) {
|
|
||||||
p->map_region[i] = newvma;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// void *mmap(void *addr, int length, int prot, int flags, int fd, int offset);
|
|
||||||
// int munmap(void *addr, int length);
|
|
||||||
uint64 sys_mmap(void)
|
|
||||||
{
|
|
||||||
uint64 addr;
|
|
||||||
int length, prot, flags, fd, offset;
|
|
||||||
argaddr(0, &addr);
|
|
||||||
argint(1, &length);
|
|
||||||
argint(2, &prot);
|
|
||||||
argint(3, &flags);
|
|
||||||
argint(4, &fd);
|
|
||||||
argint(5, &offset);
|
|
||||||
// some preliminary check
|
|
||||||
if (addr != 0 || offset != 0) panic("Unsupported non-zero value for arg addr and off");
|
|
||||||
return do_mmap(myproc(), length, prot, flags, fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 do_munmap(uint64 addr, int length)
|
|
||||||
{
|
|
||||||
struct vma* vma0 = 0;
|
|
||||||
struct proc* p = myproc();
|
|
||||||
int imap = 0;
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
if(p->map_region[i]
|
|
||||||
&& p->map_region[i]->addr <= addr
|
|
||||||
&& addr < p->map_region[i]->addr + p->map_region[i]->length) {
|
|
||||||
vma0 = p->map_region[i];
|
|
||||||
imap = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vma0 == 0) {
|
|
||||||
printf("failed to ummap %p\n", addr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// remove all relavant pages
|
|
||||||
// by reading the test code, no need to worry about non-aligned unmap
|
|
||||||
// or those unmaps which would break a vma into parts
|
|
||||||
uint64 vma_end = PGROUNDUP(vma0->addr + vma0->length);
|
|
||||||
uint64 free_start = MAX(PGROUNDDOWN(addr), vma0->addr);
|
|
||||||
uint64 free_end = MIN(PGROUNDUP(addr + length), vma_end);
|
|
||||||
for (uint64 va0 = free_start; va0 < free_end; va0 += PGSIZE) {
|
|
||||||
if (walkaddr(p->pagetable, va0)){
|
|
||||||
if (vma0->flag == MAP_SHARED) {
|
|
||||||
begin_op();
|
|
||||||
ilock(vma0->f->ip);
|
|
||||||
// int wrsz =
|
|
||||||
writei(vma0->f->ip, 1, va0, va0 + vma0->offset - vma0->addr, PGSIZE); // ? no sure if to write whole page
|
|
||||||
// printf("Write %d bytes from %p @offset=%d(off=%x,addr=%x)\n", wrsz, va0, va0 + vma0->offset - vma0->addr, vma0->offset, vma0->addr);
|
|
||||||
iunlock(vma0->f->ip);
|
|
||||||
end_op();
|
|
||||||
}
|
|
||||||
uvmunmap(p->pagetable, va0, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (free_start <= vma0->addr && free_end >= vma_end) {
|
|
||||||
// all released
|
|
||||||
fileclose(vma0->f);
|
|
||||||
memset(vma0, 0, sizeof(struct vma));
|
|
||||||
p->map_region[imap] = 0;
|
|
||||||
} else if (free_end >= vma_end) {
|
|
||||||
vma0->length = free_start - vma0->addr;
|
|
||||||
} else if (free_start <= vma0->addr) {
|
|
||||||
vma0->length -= free_end - vma0->addr;
|
|
||||||
vma0->offset += free_end - vma0->addr;
|
|
||||||
vma0->addr = free_end;
|
|
||||||
} else {
|
|
||||||
panic("unsupported unmap type");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 sys_munmap(void)
|
|
||||||
{
|
|
||||||
uint64 addr;
|
|
||||||
int length;
|
|
||||||
argaddr(0, &addr);
|
|
||||||
argint(1, &length);
|
|
||||||
return do_munmap(addr, length);
|
|
||||||
}
|
|
||||||
@ -81,18 +81,6 @@ struct trapframe {
|
|||||||
|
|
||||||
enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
||||||
|
|
||||||
struct vma {
|
|
||||||
uint64 addr;
|
|
||||||
uint length;
|
|
||||||
uint prot;
|
|
||||||
uint flag;
|
|
||||||
uint offset;
|
|
||||||
struct file* f;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NMAXVMA 20
|
|
||||||
#define MMAP_START (0x40000000)
|
|
||||||
|
|
||||||
// Per-process state
|
// Per-process state
|
||||||
struct proc {
|
struct proc {
|
||||||
struct spinlock lock;
|
struct spinlock lock;
|
||||||
@ -115,6 +103,5 @@ struct proc {
|
|||||||
struct context context; // swtch() here to run process
|
struct context context; // swtch() here to run process
|
||||||
struct file *ofile[NOFILE]; // Open files
|
struct file *ofile[NOFILE]; // Open files
|
||||||
struct inode *cwd; // Current directory
|
struct inode *cwd; // Current directory
|
||||||
struct vma* map_region[NMAXVMA];
|
|
||||||
char name[16]; // Process name (debugging)
|
char name[16]; // Process name (debugging)
|
||||||
};
|
};
|
||||||
|
|||||||
@ -101,8 +101,6 @@ extern uint64 sys_unlink(void);
|
|||||||
extern uint64 sys_link(void);
|
extern uint64 sys_link(void);
|
||||||
extern uint64 sys_mkdir(void);
|
extern uint64 sys_mkdir(void);
|
||||||
extern uint64 sys_close(void);
|
extern uint64 sys_close(void);
|
||||||
extern uint64 sys_mmap(void);
|
|
||||||
extern uint64 sys_munmap(void);
|
|
||||||
|
|
||||||
// An array mapping syscall numbers from syscall.h
|
// An array mapping syscall numbers from syscall.h
|
||||||
// to the function that handles the system call.
|
// to the function that handles the system call.
|
||||||
@ -128,8 +126,6 @@ static uint64 (*syscalls[])(void) = {
|
|||||||
[SYS_link] sys_link,
|
[SYS_link] sys_link,
|
||||||
[SYS_mkdir] sys_mkdir,
|
[SYS_mkdir] sys_mkdir,
|
||||||
[SYS_close] sys_close,
|
[SYS_close] sys_close,
|
||||||
[SYS_mmap] sys_mmap,
|
|
||||||
[SYS_munmap] sys_munmap,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -20,5 +20,3 @@
|
|||||||
#define SYS_link 19
|
#define SYS_link 19
|
||||||
#define SYS_mkdir 20
|
#define SYS_mkdir 20
|
||||||
#define SYS_close 21
|
#define SYS_close 21
|
||||||
#define SYS_mmap 22
|
|
||||||
#define SYS_munmap 23
|
|
||||||
|
|||||||
@ -55,8 +55,6 @@ sys_sleep(void)
|
|||||||
uint ticks0;
|
uint ticks0;
|
||||||
|
|
||||||
argint(0, &n);
|
argint(0, &n);
|
||||||
if(n < 0)
|
|
||||||
n = 0;
|
|
||||||
acquire(&tickslock);
|
acquire(&tickslock);
|
||||||
ticks0 = ticks;
|
ticks0 = ticks;
|
||||||
while(ticks - ticks0 < n){
|
while(ticks - ticks0 < n){
|
||||||
|
|||||||
@ -5,10 +5,6 @@
|
|||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "fcntl.h"
|
|
||||||
#include "sleeplock.h"
|
|
||||||
#include "fs.h"
|
|
||||||
#include "file.h"
|
|
||||||
|
|
||||||
struct spinlock tickslock;
|
struct spinlock tickslock;
|
||||||
uint ticks;
|
uint ticks;
|
||||||
@ -69,36 +65,9 @@ usertrap(void)
|
|||||||
intr_on();
|
intr_on();
|
||||||
|
|
||||||
syscall();
|
syscall();
|
||||||
} else if(r_scause() == 13){
|
|
||||||
int va0 = r_stval();
|
|
||||||
struct vma* vma0 = 0;
|
|
||||||
for (int i = 0; i < NMAXVMA; ++ i) {
|
|
||||||
if(p->map_region[i]
|
|
||||||
&& p->map_region[i]->addr <= va0
|
|
||||||
&& va0 < p->map_region[i]->addr + p->map_region[i]->length) {
|
|
||||||
vma0 = p->map_region[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vma0 == 0) {
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
uint64 phy_addr = (uint64)kalloc();
|
|
||||||
uint pgflag = PTE_U | (vma0->prot << 1);
|
|
||||||
// save some code... there is PTE_R/W/X = PROT_READ/WRITE/EXEC << 1
|
|
||||||
mappages(p->pagetable, va0, PGSIZE, phy_addr, pgflag);
|
|
||||||
memset((void*)phy_addr, 0, PGSIZE);
|
|
||||||
begin_op();
|
|
||||||
ilock(vma0->f->ip);
|
|
||||||
// int rdsz =
|
|
||||||
readi(vma0->f->ip, 0, phy_addr, va0 + vma0->offset - vma0->addr, PGSIZE);
|
|
||||||
// printf("Load %d bytes to %p @offset=%d\n", rdsz, va0,va0 + vma0->offset - vma0->addr);
|
|
||||||
iunlock(vma0->f->ip);
|
|
||||||
end_op();
|
|
||||||
} else if((which_dev = devintr()) != 0){
|
} else if((which_dev = devintr()) != 0){
|
||||||
// ok
|
// ok
|
||||||
} else {
|
} else {
|
||||||
bad:
|
|
||||||
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
|
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
|
||||||
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
|
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
|
||||||
setkilled(p);
|
setkilled(p);
|
||||||
|
|||||||
@ -179,10 +179,8 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
|
|||||||
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
|
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
|
||||||
if((pte = walk(pagetable, a, 0)) == 0)
|
if((pte = walk(pagetable, a, 0)) == 0)
|
||||||
panic("uvmunmap: walk");
|
panic("uvmunmap: walk");
|
||||||
if((*pte & PTE_V) == 0){
|
if((*pte & PTE_V) == 0)
|
||||||
printf("%p\n", va);
|
|
||||||
panic("uvmunmap: not mapped");
|
panic("uvmunmap: not mapped");
|
||||||
}
|
|
||||||
if(PTE_FLAGS(*pte) == PTE_V)
|
if(PTE_FLAGS(*pte) == PTE_V)
|
||||||
panic("uvmunmap: not a leaf");
|
panic("uvmunmap: not a leaf");
|
||||||
if(do_free){
|
if(do_free){
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "kernel/types.h"
|
#include "kernel/types.h"
|
||||||
#include "kernel/stat.h"
|
#include "kernel/stat.h"
|
||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
|
||||||
char buf[512];
|
char buf[512];
|
||||||
@ -33,7 +32,7 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(i = 1; i < argc; i++){
|
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]);
|
fprintf(2, "cat: cannot open %s\n", argv[i]);
|
||||||
exit(1);
|
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/types.h"
|
||||||
#include "kernel/stat.h"
|
#include "kernel/stat.h"
|
||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@ -52,7 +51,7 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(i = 2; i < argc; i++){
|
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]);
|
printf("grep: cannot open %s\n", argv[i]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
#include "kernel/stat.h"
|
#include "kernel/stat.h"
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
#include "kernel/fs.h"
|
#include "kernel/fs.h"
|
||||||
#include "kernel/fcntl.h"
|
|
||||||
|
|
||||||
char*
|
char*
|
||||||
fmtname(char *path)
|
fmtname(char *path)
|
||||||
@ -31,7 +30,7 @@ ls(char *path)
|
|||||||
struct dirent de;
|
struct dirent de;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if((fd = open(path, O_RDONLY)) < 0){
|
if((fd = open(path, 0)) < 0){
|
||||||
fprintf(2, "ls: cannot open %s\n", path);
|
fprintf(2, "ls: cannot open %s\n", path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
297
user/mmaptest.c
297
user/mmaptest.c
@ -1,297 +0,0 @@
|
|||||||
#include "kernel/param.h"
|
|
||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "kernel/types.h"
|
|
||||||
#include "kernel/stat.h"
|
|
||||||
#include "kernel/riscv.h"
|
|
||||||
#include "kernel/fs.h"
|
|
||||||
#include "user/user.h"
|
|
||||||
|
|
||||||
void mmap_test();
|
|
||||||
void fork_test();
|
|
||||||
char buf[BSIZE];
|
|
||||||
|
|
||||||
#define MAP_FAILED ((char *) -1)
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
mmap_test();
|
|
||||||
fork_test();
|
|
||||||
printf("mmaptest: all tests succeeded\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *testname = "???";
|
|
||||||
|
|
||||||
void
|
|
||||||
err(char *why)
|
|
||||||
{
|
|
||||||
printf("mmaptest: %s failed: %s, pid=%d\n", testname, why, getpid());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// check the content of the two mapped pages.
|
|
||||||
//
|
|
||||||
void
|
|
||||||
_v1(char *p)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < PGSIZE*2; i++) {
|
|
||||||
if (i < PGSIZE + (PGSIZE/2)) {
|
|
||||||
if (p[i] != 'A') {
|
|
||||||
printf("mismatch at %d, wanted 'A', got 0x%x\n", i, p[i]);
|
|
||||||
err("v1 mismatch (1)");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (p[i] != 0) {
|
|
||||||
printf("mismatch at %d, wanted zero, got 0x%x\n", i, p[i]);
|
|
||||||
err("v1 mismatch (2)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// create a file to be mapped, containing
|
|
||||||
// 1.5 pages of 'A' and half a page of zeros.
|
|
||||||
//
|
|
||||||
void
|
|
||||||
makefile(const char *f)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int n = PGSIZE/BSIZE;
|
|
||||||
|
|
||||||
unlink(f);
|
|
||||||
int fd = open(f, O_WRONLY | O_CREATE);
|
|
||||||
if (fd == -1)
|
|
||||||
err("open");
|
|
||||||
memset(buf, 'A', BSIZE);
|
|
||||||
// write 1.5 page
|
|
||||||
for (i = 0; i < n + n/2; i++) {
|
|
||||||
if (write(fd, buf, BSIZE) != BSIZE)
|
|
||||||
err("write 0 makefile");
|
|
||||||
}
|
|
||||||
if (close(fd) == -1)
|
|
||||||
err("close");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
mmap_test(void)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
int i;
|
|
||||||
const char * const f = "mmap.dur";
|
|
||||||
printf("mmap_test starting\n");
|
|
||||||
testname = "mmap_test";
|
|
||||||
|
|
||||||
//
|
|
||||||
// create a file with known content, map it into memory, check that
|
|
||||||
// the mapped memory has the same bytes as originally written to the
|
|
||||||
// file.
|
|
||||||
//
|
|
||||||
makefile(f);
|
|
||||||
if ((fd = open(f, O_RDONLY)) == -1)
|
|
||||||
err("open");
|
|
||||||
|
|
||||||
printf("test mmap f\n");
|
|
||||||
//
|
|
||||||
// this call to mmap() asks the kernel to map the content
|
|
||||||
// of open file fd into the address space. the first
|
|
||||||
// 0 argument indicates that the kernel should choose the
|
|
||||||
// virtual address. the second argument indicates how many
|
|
||||||
// bytes to map. the third argument indicates that the
|
|
||||||
// mapped memory should be read-only. the fourth argument
|
|
||||||
// indicates that, if the process modifies the mapped memory,
|
|
||||||
// that the modifications should not be written back to
|
|
||||||
// the file nor shared with other processes mapping the
|
|
||||||
// same file (of course in this case updates are prohibited
|
|
||||||
// due to PROT_READ). the fifth argument is the file descriptor
|
|
||||||
// of the file to be mapped. the last argument is the starting
|
|
||||||
// offset in the file.
|
|
||||||
//
|
|
||||||
char *p = mmap(0, PGSIZE*2, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
||||||
if (p == MAP_FAILED)
|
|
||||||
err("mmap (1)");
|
|
||||||
_v1(p);
|
|
||||||
if (munmap(p, PGSIZE*2) == -1)
|
|
||||||
err("munmap (1)");
|
|
||||||
|
|
||||||
printf("test mmap f: OK\n");
|
|
||||||
|
|
||||||
printf("test mmap private\n");
|
|
||||||
// should be able to map file opened read-only with private writable
|
|
||||||
// mapping
|
|
||||||
p = mmap(0, PGSIZE*2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
|
||||||
if (p == MAP_FAILED)
|
|
||||||
err("mmap (2)");
|
|
||||||
if (close(fd) == -1)
|
|
||||||
err("close");
|
|
||||||
_v1(p);
|
|
||||||
for (i = 0; i < PGSIZE*2; i++)
|
|
||||||
p[i] = 'Z';
|
|
||||||
if (munmap(p, PGSIZE*2) == -1)
|
|
||||||
err("munmap (2)");
|
|
||||||
|
|
||||||
printf("test mmap private: OK\n");
|
|
||||||
|
|
||||||
printf("test mmap read-only\n");
|
|
||||||
|
|
||||||
// check that mmap doesn't allow read/write mapping of a
|
|
||||||
// file opened read-only.
|
|
||||||
if ((fd = open(f, O_RDONLY)) == -1)
|
|
||||||
err("open");
|
|
||||||
p = mmap(0, PGSIZE*3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
if (p != MAP_FAILED)
|
|
||||||
err("mmap call should have failed");
|
|
||||||
if (close(fd) == -1)
|
|
||||||
err("close");
|
|
||||||
|
|
||||||
printf("test mmap read-only: OK\n");
|
|
||||||
|
|
||||||
printf("test mmap read/write\n");
|
|
||||||
|
|
||||||
// check that mmap does allow read/write mapping of a
|
|
||||||
// file opened read/write.
|
|
||||||
if ((fd = open(f, O_RDWR)) == -1)
|
|
||||||
err("open");
|
|
||||||
p = mmap(0, PGSIZE*3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
if (p == MAP_FAILED)
|
|
||||||
err("mmap (3)");
|
|
||||||
if (close(fd) == -1)
|
|
||||||
err("close");
|
|
||||||
|
|
||||||
// check that the mapping still works after close(fd).
|
|
||||||
_v1(p);
|
|
||||||
|
|
||||||
// write the mapped memory.
|
|
||||||
for (i = 0; i < PGSIZE*2; i++)
|
|
||||||
p[i] = 'Z';
|
|
||||||
|
|
||||||
// unmap just the first two of three pages of mapped memory.
|
|
||||||
if (munmap(p, PGSIZE*2) == -1)
|
|
||||||
err("munmap (3)");
|
|
||||||
|
|
||||||
printf("test mmap read/write: OK\n");
|
|
||||||
|
|
||||||
printf("test mmap dirty\n");
|
|
||||||
|
|
||||||
// check that the writes to the mapped memory were
|
|
||||||
// written to the file.
|
|
||||||
if ((fd = open(f, O_RDWR)) == -1)
|
|
||||||
err("open");
|
|
||||||
for (i = 0; i < PGSIZE + (PGSIZE/2); i++){
|
|
||||||
char b;
|
|
||||||
if (read(fd, &b, 1) != 1)
|
|
||||||
err("read (1)");
|
|
||||||
if (b != 'Z')
|
|
||||||
err("file does not contain modifications");
|
|
||||||
}
|
|
||||||
if (close(fd) == -1)
|
|
||||||
err("close");
|
|
||||||
|
|
||||||
printf("test mmap dirty: OK\n");
|
|
||||||
|
|
||||||
printf("test not-mapped unmap\n");
|
|
||||||
|
|
||||||
// unmap the rest of the mapped memory.
|
|
||||||
if (munmap(p+PGSIZE*2, PGSIZE) == -1)
|
|
||||||
err("munmap (4)");
|
|
||||||
|
|
||||||
printf("test not-mapped unmap: OK\n");
|
|
||||||
|
|
||||||
printf("test mmap two files\n");
|
|
||||||
|
|
||||||
//
|
|
||||||
// mmap two files at the same time.
|
|
||||||
//
|
|
||||||
int fd1;
|
|
||||||
if((fd1 = open("mmap1", O_RDWR|O_CREATE)) < 0)
|
|
||||||
err("open mmap1");
|
|
||||||
if(write(fd1, "12345", 5) != 5)
|
|
||||||
err("write mmap1");
|
|
||||||
char *p1 = mmap(0, PGSIZE, PROT_READ, MAP_PRIVATE, fd1, 0);
|
|
||||||
if(p1 == MAP_FAILED)
|
|
||||||
err("mmap mmap1");
|
|
||||||
close(fd1);
|
|
||||||
unlink("mmap1");
|
|
||||||
|
|
||||||
int fd2;
|
|
||||||
if((fd2 = open("mmap2", O_RDWR|O_CREATE)) < 0)
|
|
||||||
err("open mmap2");
|
|
||||||
if(write(fd2, "67890", 5) != 5)
|
|
||||||
err("write mmap2");
|
|
||||||
char *p2 = mmap(0, PGSIZE, PROT_READ, MAP_PRIVATE, fd2, 0);
|
|
||||||
if(p2 == MAP_FAILED)
|
|
||||||
err("mmap mmap2");
|
|
||||||
close(fd2);
|
|
||||||
unlink("mmap2");
|
|
||||||
|
|
||||||
if(memcmp(p1, "12345", 5) != 0)
|
|
||||||
err("mmap1 mismatch");
|
|
||||||
if(memcmp(p2, "67890", 5) != 0)
|
|
||||||
err("mmap2 mismatch");
|
|
||||||
|
|
||||||
munmap(p1, PGSIZE);
|
|
||||||
if(memcmp(p2, "67890", 5) != 0)
|
|
||||||
err("mmap2 mismatch (2)");
|
|
||||||
munmap(p2, PGSIZE);
|
|
||||||
|
|
||||||
printf("test mmap two files: OK\n");
|
|
||||||
|
|
||||||
printf("mmap_test: ALL OK\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// mmap a file, then fork.
|
|
||||||
// check that the child sees the mapped file.
|
|
||||||
//
|
|
||||||
void
|
|
||||||
fork_test(void)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
int pid;
|
|
||||||
const char * const f = "mmap.dur";
|
|
||||||
|
|
||||||
printf("fork_test starting\n");
|
|
||||||
testname = "fork_test";
|
|
||||||
|
|
||||||
// mmap the file twice.
|
|
||||||
makefile(f);
|
|
||||||
if ((fd = open(f, O_RDONLY)) == -1)
|
|
||||||
err("open");
|
|
||||||
unlink(f);
|
|
||||||
char *p1 = mmap(0, PGSIZE*2, PROT_READ, MAP_SHARED, fd, 0);
|
|
||||||
if (p1 == MAP_FAILED)
|
|
||||||
err("mmap (4)");
|
|
||||||
char *p2 = mmap(0, PGSIZE*2, PROT_READ, MAP_SHARED, fd, 0);
|
|
||||||
if (p2 == MAP_FAILED)
|
|
||||||
err("mmap (5)");
|
|
||||||
|
|
||||||
// read just 2nd page.
|
|
||||||
if(*(p1+PGSIZE) != 'A')
|
|
||||||
err("fork mismatch (1)");
|
|
||||||
|
|
||||||
if((pid = fork()) < 0)
|
|
||||||
err("fork");
|
|
||||||
if (pid == 0) {
|
|
||||||
_v1(p1);
|
|
||||||
munmap(p1, PGSIZE); // just the first page
|
|
||||||
exit(0); // tell the parent that the mapping looks OK.
|
|
||||||
}
|
|
||||||
|
|
||||||
int status = -1;
|
|
||||||
wait(&status);
|
|
||||||
|
|
||||||
if(status != 0){
|
|
||||||
printf("fork_test failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that the parent's mappings are still there.
|
|
||||||
_v1(p1);
|
|
||||||
_v1(p2);
|
|
||||||
|
|
||||||
printf("fork_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);
|
||||||
|
}
|
||||||
@ -22,8 +22,6 @@ int getpid(void);
|
|||||||
char* sbrk(int);
|
char* sbrk(int);
|
||||||
int sleep(int);
|
int sleep(int);
|
||||||
int uptime(void);
|
int uptime(void);
|
||||||
void *mmap(void *addr, int length, int prot, int flags, int fd, int offset);
|
|
||||||
int munmap(void *addr, int length);
|
|
||||||
|
|
||||||
// ulib.c
|
// ulib.c
|
||||||
int stat(const char*, struct stat*);
|
int stat(const char*, struct stat*);
|
||||||
|
|||||||
@ -36,5 +36,3 @@ entry("getpid");
|
|||||||
entry("sbrk");
|
entry("sbrk");
|
||||||
entry("sleep");
|
entry("sleep");
|
||||||
entry("uptime");
|
entry("uptime");
|
||||||
entry("mmap");
|
|
||||||
entry("munmap");
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "kernel/types.h"
|
#include "kernel/types.h"
|
||||||
#include "kernel/stat.h"
|
#include "kernel/stat.h"
|
||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
|
||||||
char buf[512];
|
char buf[512];
|
||||||
@ -44,7 +43,7 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(i = 1; i < argc; i++){
|
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]);
|
printf("wc: cannot open %s\n", argv[i]);
|
||||||
exit(1);
|
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