提交 f32f3638 创建 作者: rsc's avatar rsc

Various cleanup:

- Got rid of dummy proc[0]. Now proc[0] is init. - Added initcode.S to exec /init, so that /init is just a regular binary. - Moved exec out of sysfile to exec.c - Moved code dealing with fs guts (like struct inode) from sysfile.c to fs.c. Code dealing with system call arguments stays in sysfile.c - Refactored directory routines in fs.c; should be simpler. - Changed iget to return *unlocked* inode structure. This solves the lookup-then-use race in namei without introducing deadlocks. It also enabled getting rid of the dummy proc[0].
上级 2d61a40b
......@@ -11,14 +11,15 @@ proc.c:
factor out switching and scheduling code from process code
kalloc.c
more cleanups
shuffle for formatting
ide.c: synchronous disk write -> polling disk write. search for
(a)synchronous; xv6 doesn't have asynchronous writes.
syscall.c:
cannot convince runoff1 to split the extern lists to fill previous page completely.
fs.c: split all name operations off in name.c? (starting with namei but move
fs.c: split all name operations off in name.c? (starting with namei but
wdir keep in fs.c)
locking?
shuffle for formatting
pipe.c:
more comments?
......@@ -31,6 +32,19 @@ sysfile.c:
general:
sizeof parens?
bio.c:
decide odd or even
bwrite doesn't need a second argument
file.c:
move fileincref onto page 1?
L=$HOME/mit/l
(for i in *.c; do xoc -x xgnu -x ./nodecleq.zeta --typesonly $i; done) 2>&1 | grep warning
saw random sharedfd failure.
why does fdalloc consume reference?
why mkdir and create?
......@@ -21,6 +21,7 @@ OBJS = \
vectors.o\
bio.o\
fs.o\
exec.o\
8253pit.o\
# Cross-compiling (e.g., on Mac OS X)
......@@ -34,7 +35,7 @@ LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump
# On newer gcc you may need to add -fno-stack-protector to $(CFLAGS)
CFLAGS = -fno-builtin -O2 -Wall -MD
CFLAGS = -fno-builtin -O2 -Wall -MD -ggdb -fno-stack-protector
AS = $(TOOLPREFIX)gas
xv6.img : bootblock kernel fs.img
......@@ -50,12 +51,16 @@ bootblock : bootasm.S bootmain.c
$(OBJCOPY) -S -O binary bootblock.o bootblock
./sign.pl bootblock
kernel : $(OBJS) bootother.S _init
kernel : $(OBJS) bootother.S initcode.S
$(CC) -nostdinc -I. -c bootother.S
$(LD) -N -e start -Ttext 0x7000 -o bootother.out bootother.o
$(OBJCOPY) -S -O binary bootother.out bootother
$(OBJDUMP) -S bootother.o > bootother.asm
$(LD) -Ttext 0x100000 -e main0 -o kernel $(OBJS) -b binary bootother _init
$(CC) -nostdinc -I. -c initcode.S
$(LD) -N -e start -Ttext 0 -o initcode.out initcode.o
$(OBJCOPY) -S -O binary initcode.out initcode
$(OBJDUMP) -S initcode.o > initcode.asm
$(LD) -Ttext 0x100000 -e main0 -o kernel $(OBJS) -b binary initcode bootother
$(OBJDUMP) -S kernel > kernel.asm
$(OBJDUMP) -t kernel | awk '/SYMBOL TABLE/ { go=1; next } go {print $$1, $$NF}' >kernel.sym
......@@ -132,7 +137,7 @@ PRINT = \
proc.h proc.c setjmp.S kalloc.c\
syscall.h trapasm.S traps.h trap.c vectors.pl syscall.c sysproc.c\
buf.h dev.h fcntl.h stat.h file.h fs.h fsvar.h file.c fs.c bio.c ide.c sysfile.c\
pipe.c\
pipe.c exec.c\
mp.h ioapic.h mp.c lapic.c ioapic.c picirq.c\
console.c\
string.c\
......
......@@ -40,6 +40,7 @@ int memcmp(const void*, const void*, uint);
void* memmove(void*, const void*, uint);
int strncmp(const char*, const char*, uint);
char* safestrcpy(char*, const char*, int);
int strlen(const char*);
// syscall.c
void syscall(void);
......@@ -135,11 +136,16 @@ int readi(struct inode*, char*, uint, uint);
int writei(struct inode*, char*, uint, uint);
struct inode* mknod(char*, short, short, short);
struct inode* dircreat(struct inode*, char*, int, short, short, short);
int dirlookup(struct inode*, char*, int, uint*, uint*);
struct inode* dirlookup(struct inode*, char*, int, uint*);
int unlink(char*);
void iupdate(struct inode*);
int link(char*, char*);
struct inode* igetroot(void);
int mkdir(char *path);
struct inode* create(char *path);
// exec.c
int exec(char*, char**);
// number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
#include "types.h"
#include "stat.h"
#include "param.h"
#include "mmu.h"
#include "proc.h"
#include "defs.h"
#include "x86.h"
#include "traps.h"
#include "syscall.h"
#include "spinlock.h"
#include "buf.h"
#include "fs.h"
#include "fsvar.h"
#include "elf.h"
#include "file.h"
#include "fcntl.h"
int
exec(char *path, char **argv)
{
uint sz, sp, p1, p2;
int i, nargs, argbytes, len;
struct inode *ip;
struct elfhdr elf;
struct proghdr ph;
char *mem;
char *s, *last;
sz = 0;
mem = 0;
if((ip = namei(path)) == 0)
return -1;
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
goto bad;
if(elf.magic != ELF_MAGIC)
goto bad;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
sizeof(ph)) != sizeof(ph))
goto bad;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.memsz < ph.filesz)
goto bad;
sz += ph.memsz;
}
sz += 4096 - (sz % 4096);
sz += 4096;
mem = kalloc(sz);
if(mem == 0)
goto bad;
memset(mem, 0, sz);
argbytes = 0;
for(i = 0; argv[i]; i++){
len = strlen(argv[i]);
argbytes += len + 1;
}
nargs = i;
// argn\0
// ...
// arg0\0
// 0
// ptr to argn
// ...
// 12: ptr to arg0
// 8: argv (points to ptr to arg0)
// 4: argc
// 0: fake return pc
sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4;
*(uint*)(mem + sp) = 0xffffffff;
*(uint*)(mem + sp + 4) = nargs;
*(uint*)(mem + sp + 8) = (uint)(sp + 12);
p1 = sp + 12;
p2 = sp + 12 + (nargs + 1) * 4;
for(i = 0; i < nargs; i++){
len = strlen(argv[i]);
memmove(mem + p2, argv[i], len + 1);
*(uint*)(mem + p1) = p2;
p1 += 4;
p2 += len + 1;
}
*(uint*)(mem + p1) = 0;
// Save name for debugging.
for(last=s=path; *s; s++)
if(*s == '/')
last = s+1;
safestrcpy(cp->name, last, sizeof cp->name);
// commit to the new image.
kfree(cp->mem, cp->sz);
cp->sz = sz;
cp->mem = mem;
mem = 0;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
sizeof(ph)) != sizeof(ph))
goto bad2;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.va + ph.memsz > sz)
goto bad2;
if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
goto bad2;
memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
}
iput(ip);
cp->tf->eip = elf.entry;
cp->tf->esp = sp;
setupsegs(cp);
return 0;
bad:
if(mem)
kfree(mem, sz);
iput(ip);
return -1;
bad2:
iput(ip);
proc_exit();
return 0;
}
差异被折叠。
......@@ -4,7 +4,7 @@ struct inode {
uint dev; // Device number
uint inum; // Inode number
int ref; // Reference count
int busy; // Is the inode "locked"?
int flags; // I_BUSY, I_VALID
short type; // copy of disk inode
short major;
......@@ -16,6 +16,5 @@ struct inode {
#define ROOTDEV 1 // Device number of root file system
#define NAMEI_LOOKUP 1
#define NAMEI_CREATE 2
#define NAMEI_DELETE 3
#define I_BUSY 0x1
#define I_VALID 0x2
# Initial process execs /init.
#include "syscall.h"
#include "traps.h"
# exec(init, argv)
start:
pushl $argv
pushl $init
pushl $0
movl $SYS_exec, %eax
int $T_SYSCALL
# for(;;) exit();
exit:
movl $SYS_exit, %eax
int $T_SYSCALL
jmp exit
# "/init\0"
init:
.string "/init\0"
.p2align 2
argv:
.long init
.long 0
......@@ -11,9 +11,8 @@
#include "spinlock.h"
extern char edata[], end[];
extern uchar _binary__init_start[], _binary__init_size[];
void process0();
void proc0init();
// Bootstrap processor starts running C code here.
// This is called main0 not main so that it can have
......@@ -24,7 +23,6 @@ main0(void)
{
int i;
static int bcpu; // cannot be on stack
struct proc *p;
// clear BSS
memset(edata, 0, end - edata);
......@@ -54,15 +52,6 @@ main0(void)
fileinit();
iinit(); // i-node table
// initialize process 0
p = &proc[0];
p->state = RUNNABLE;
p->kstack = kalloc(KSTACKSIZE);
// cause proc[0] to start in kernel at process0
p->jmpbuf.eip = (uint) process0;
p->jmpbuf.esp = (uint) (p->kstack + KSTACKSIZE - 4);
// make sure there's a TSS
setupsegs(0);
......@@ -86,6 +75,9 @@ main0(void)
cpus[cpu()].nlock--;
sti();
// initialize process 0
proc0init();
scheduler();
}
......@@ -114,77 +106,45 @@ mpmain(void)
scheduler();
}
// proc[0] starts here, called by scheduler() in the ordinary way.
char initcode[] = {
/* push ptr to argv */ 0x6a, 0x1c,
/* push ptr to "/init" */ 0x6a, 0x16,
/* push fake ret addr */ 0x6a, 0x00,
/* mov $SYS_exec, %eax */ 0xb8, 0x09, 0x00, 0x00, 0x00,
/* int $0x30 */ 0xcd, 0x30,
/* Lx: */
/* mov $SYS_exit, %eax */ 0xb8, 0x02, 0x00, 0x00, 0x00,
/* int $0x30 */ 0xcd, 0x30,
/* jmp Lx */ 0xeb, 0xf7,
/* "/init\0" */ 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x00,
/* ptr to "/init" */ 0x16, 0x00, 0x00, 0x00,
/* 0 */ 0x00, 0x00, 0x00, 0x00
};
void
process0(void)
proc0init(void)
{
extern struct spinlock proc_table_lock;
struct proc *p0, *p1;
struct trapframe tf;
release(&proc_table_lock);
p0 = &proc[0];
p0->cwd = igetroot();
iunlock(p0->cwd);
// Dummy user memory to make copyproc() happy.
// Must be big enough to hold the init binary and stack.
p0->sz = 2*PAGE;
p0->mem = kalloc(p0->sz);
// Fake a trap frame as if a user process had made a system
// call, so that copyproc will have a place for the new
// process to return to.
p0->tf = &tf;
memset(p0->tf, 0, sizeof(struct trapframe));
p0->tf->es = p0->tf->ds = p0->tf->ss = (SEG_UDATA << 3) | DPL_USER;
p0->tf->cs = (SEG_UCODE << 3) | DPL_USER;
p0->tf->eflags = FL_IF;
p0->tf->esp = p0->sz;
struct proc *p;
extern uchar _binary_initcode_start[], _binary_initcode_size[];
// Push bogus return address, both to cause problems
// if main returns and also because gcc can generate
// function prologs that expect to be able to read the
// return address off the stack without causing a fault.
p0->tf->esp -= 4;
*(uint*)(p0->mem + p0->tf->esp) = 0xefefefef;
p1 = copyproc(p0);
load_icode(p1, _binary__init_start, (uint) _binary__init_size);
p1->state = RUNNABLE;
safestrcpy(p1->name, "init", sizeof p1->name);
p = copyproc(0);
p->sz = PAGE;
p->mem = kalloc(p->sz);
p->cwd = igetroot();
memset(&p->tf, 0, sizeof p->tf);
p->tf->es = p->tf->ds = p->tf->ss = (SEG_UDATA << 3) | DPL_USER;
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
p->tf->eflags = FL_IF;
p->tf->esp = p->sz;
// Push dummy return address to placate gcc.
p->tf->esp -= 4;
*(uint*)(p->mem + p->tf->esp) = 0xefefefef;
proc_wait();
panic("init exited");
p->tf->eip = 0;
memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
safestrcpy(p->name, "initcode", sizeof p->name);
p->state = RUNNABLE;
}
void
load_icode(struct proc *p, uchar *binary, uint size)
{
int i;
struct elfhdr *elf;
struct proghdr *ph;
elf = (struct elfhdr*) binary;
if(elf->magic != ELF_MAGIC)
panic("load_icode: not an ELF binary");
p->tf->eip = elf->entry;
// Map and load segments as directed.
ph = (struct proghdr*) (binary + elf->phoff);
for(i = 0; i < elf->phnum; i++, ph++) {
if(ph->type != ELF_PROG_LOAD)
continue;
if(ph->va + ph->memsz < ph->va)
panic("load_icode: overflow in proghdr");
if(ph->va + ph->memsz >= p->sz)
panic("load_icode: icode too large");
// Load/clear the segment
memmove(p->mem + ph->va, binary + ph->offset, ph->filesz);
memset(p->mem + ph->va + ph->filesz, 0, ph->memsz - ph->filesz);
}
}
......@@ -109,47 +109,43 @@ copyproc(struct proc *p)
return 0;
}
np->pid = next_pid++;
np->ppid = p->pid;
release(&proc_table_lock);
// Copy user memory.
np->sz = p->sz;
np->mem = kalloc(np->sz);
if(np->mem == 0){
np->state = UNUSED;
return 0;
}
memmove(np->mem, p->mem, np->sz);
// Allocate kernel stack.
np->kstack = kalloc(KSTACKSIZE);
if(np->kstack == 0){
kfree(np->mem, np->sz);
np->mem = 0;
if((np->kstack = kalloc(KSTACKSIZE)) == 0){
np->state = UNUSED;
return 0;
}
// Copy trapframe registers from parent.
np->tf = (struct trapframe*)(np->kstack + KSTACKSIZE) - 1;
memmove(np->tf, p->tf, sizeof(*np->tf));
// Clear %eax so that fork system call returns 0 in child.
np->tf->eax = 0;
if(p){ // Copy process state from p.
np->ppid = p->pid;
memmove(np->tf, p->tf, sizeof *np->tf);
np->sz = p->sz;
if((np->mem = kalloc(np->sz)) == 0){
kfree(np->kstack, KSTACKSIZE);
np->kstack = 0;
np->state = UNUSED;
return 0;
}
memmove(np->mem, p->mem, np->sz);
for(i = 0; i < NOFILE; i++){
np->ofile[i] = p->ofile[i];
if(np->ofile[i])
fileincref(np->ofile[i]);
}
np->cwd = iincref(p->cwd);
}
// Set up new jmpbuf to start executing at forkret (see below).
memset(&np->jmpbuf, 0, sizeof np->jmpbuf);
np->jmpbuf.eip = (uint)forkret;
np->jmpbuf.esp = (uint)np->tf - 4;
// Copy file descriptors
for(i = 0; i < NOFILE; i++){
np->ofile[i] = p->ofile[i];
if(np->ofile[i])
fileincref(np->ofile[i]);
}
np->cwd = iincref(p->cwd);
// Clear %eax so that fork system call returns 0 in child.
np->tf->eax = 0;
return np;
}
......
......@@ -75,3 +75,13 @@ safestrcpy(char *s, const char *t, int n)
return os;
}
int
strlen(const char *s)
{
int n;
for(n = 0; s[n]; n++)
;
return n;
}
......@@ -53,7 +53,6 @@ fetchstr(struct proc *p, uint addr, char **pp)
int
argint(int argno, int *ip)
{
return fetchint(cp, cp->tf->esp + 4 + 4*argno, ip);
}
......
......@@ -114,42 +114,22 @@ sys_close(void)
int
sys_open(void)
{
struct inode *ip, *dp;
char *path, *name;
int namelen;
int omode;
int fd, dev;
uint inum;
char *path;
int fd, omode;
struct file *f;
struct inode *ip;
if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
return -1;
switch(omode & O_CREATE){
default:
case 0: // regular open
if((ip = namei(path)) == 0)
return -1;
break;
case O_CREATE:
if((dp = nameiparent(path, &name, &namelen)) == 0)
return -1;
if(dirlookup(dp, name, namelen, 0, &inum) >= 0){
dev = dp->dev;
iput(dp);
ip = iget(dev, inum);
}else{
if((ip = dircreat(dp, name, namelen, T_FILE, 0, 0)) == 0){
iput(dp);
return -1;
}
iput(dp);
}
break;
}
if(omode & O_CREATE)
ip = create(path);
else
ip = namei(path);
if(ip == 0)
return -1;
if(ip->type == T_DIR && (omode & (O_RDWR|O_WRONLY|O_CREATE))){
if(ip->type == T_DIR && (omode & (O_RDWR|O_WRONLY))){
iput(ip);
return -1;
}
......@@ -194,6 +174,7 @@ sys_mknod(void)
argint(2, &major) < 0 || argint(3, &minor) < 0)
return -1;
// XXX why this check?
if(len >= DIRSIZ)
return -1;
......@@ -206,45 +187,11 @@ sys_mknod(void)
int
sys_mkdir(void)
{
struct inode *nip;
struct inode *dp;
char *name, *path;
struct dirent de;
int namelen;
char *path;
if(argstr(0, &path) < 0)
return -1;
dp = nameiparent(path, &name, &namelen);
if(dp == 0)
return -1;
if(dirlookup(dp, name, namelen, 0, 0) >= 0){
iput(dp);
return -1;
}
nip = dircreat(dp, name, namelen, T_DIR, 0, 0);
if(nip == 0){
iput(dp);
return -1;
}
dp->nlink++;
iupdate(dp);
memset(de.name, '\0', DIRSIZ);
de.name[0] = '.';
de.inum = nip->inum;
writei(nip, (char*) &de, 0, sizeof(de));
de.inum = dp->inum;
de.name[1] = '.';
writei(nip, (char*) &de, sizeof(de), sizeof(de));
iput(dp);
iput(nip);
return 0;
return mkdir(path);
}
int
......@@ -315,132 +262,30 @@ sys_link(void)
return link(old, new);
}
#define ARGMAX 10
int
sys_exec(void)
{
uint sz=0, ap, sp, p1, p2;
int i, nargs, argbytes, len;
struct inode *ip;
struct elfhdr elf;
struct proghdr ph;
char *mem = 0;
char *path, *s, *last;
uint argv;
if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0)
return -1;
char *path, *argv[ARGMAX];
int i;
uint uargv, uarg;
if((ip = namei(path)) == 0)
if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0)
return -1;
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
goto bad;
if(elf.magic != ELF_MAGIC)
goto bad;
sz = 0;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
sizeof(ph)) != sizeof(ph))
goto bad;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.memsz < ph.filesz)
goto bad;
sz += ph.memsz;
}
sz += 4096 - (sz % 4096);
sz += 4096;
mem = kalloc(sz);
if(mem == 0)
goto bad;
memset(mem, 0, sz);
nargs = 0;
argbytes = 0;
for(i = 0;; i++){
if(fetchint(cp, argv + 4*i, (int*)&ap) < 0)
goto bad;
if(ap == 0)
memset(argv, 0, sizeof argv);
for(i=0;; i++){
if(i >= ARGMAX)
return -1;
if(fetchint(cp, uargv+4*i, (int*)&uarg) < 0)
return -1;
if(uarg == 0){
argv[i] = 0;
break;
len = fetchstr(cp, ap, &s);
if(len < 0)
goto bad;
nargs++;
argbytes += len + 1;
}
// argn\0
// ...
// arg0\0
// 0
// ptr to argn
// ...
// 12: ptr to arg0
// 8: argv (points to ptr to arg0)
// 4: argc
// 0: fake return pc
sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4;
*(uint*)(mem + sp) = 0xffffffff;
*(uint*)(mem + sp + 4) = nargs;
*(uint*)(mem + sp + 8) = (uint)(sp + 12);
p1 = sp + 12;
p2 = sp + 12 + (nargs + 1) * 4;
for(i = 0; i < nargs; i++){
fetchint(cp, argv + 4*i, (int*)&ap);
len = fetchstr(cp, ap, &s);
memmove(mem + p2, s, len + 1);
*(uint*)(mem + p1) = p2;
p1 += 4;
p2 += len + 1;
}
*(uint*)(mem + p1) = 0;
// Save name for debugging.
for(last=s=path; *s; s++)
if(*s == '/')
last = s+1;
safestrcpy(cp->name, last, sizeof cp->name);
// commit to the new image.
kfree(cp->mem, cp->sz);
cp->sz = sz;
cp->mem = mem;
mem = 0;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
sizeof(ph)) != sizeof(ph))
goto bad2;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.va + ph.memsz > sz)
goto bad2;
if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
goto bad2;
memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
}
if(fetchstr(cp, uarg, &argv[i]) < 0)
return -1;
}
iput(ip);
cp->tf->eip = elf.entry;
cp->tf->esp = sp;
setupsegs(cp);
return 0;
bad:
if(mem)
kfree(mem, sz);
iput(ip);
return -1;
bad2:
iput(ip);
proc_exit();
return 0;
return exec(path, argv);
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论