primitive exec

This commit is contained in:
rtm 2006-07-27 21:10:00 +00:00
parent 54a4b00346
commit c59361f143
10 changed files with 242 additions and 41 deletions

View file

@ -73,8 +73,8 @@ userfs : userfs.o $(ULIB)
mkfs : mkfs.c fs.h
cc -o mkfs mkfs.c
fs.img : mkfs
./mkfs fs.img
fs.img : mkfs usertests
./mkfs fs.img usertests
-include *.d

1
defs.h
View file

@ -102,3 +102,4 @@ void iunlock(struct inode *ip);
void iincref(struct inode *ip);
void iput(struct inode *ip);
struct inode * namei(char *path);
int readi(struct inode *ip, void *xdst, uint off, uint n);

23
fs.c
View file

@ -133,6 +133,29 @@ bmap(struct inode *ip, uint bn)
return x;
}
#define min(a, b) ((a) < (b) ? (a) : (b))
int
readi(struct inode *ip, void *xdst, uint off, uint n)
{
char *dst = (char *) xdst;
uint target = n, n1;
struct buf *bp;
while(n > 0 && off < ip->size){
bp = bread(ip->dev, bmap(ip, off / 512));
n1 = min(n, ip->size - off);
n1 = min(n1, 512 - (off % 512));
memmove(dst, bp->data + (off % 512), n1);
n -= n1;
off += n1;
dst += n1;
brelse(bp);
}
return target - n;
}
struct inode *
namei(char *path)
{

1
main.c
View file

@ -100,6 +100,7 @@ mpmain(void)
lapic_enableintr();
// Enable interrupts on this processor.
cprintf("cpu %d initial nlock %d\n", cpu(), cpus[cpu()].nlock);
cpus[cpu()].nlock--;
sti();

148
mkfs.c
View file

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include "types.h"
#include "param.h"
#include "fs.h"
@ -10,14 +11,17 @@
int nblocks = 1009;
int ninodes = 100;
int fd;
int fsfd;
struct superblock sb;
char zeroes[512];
uint freeblock;
uint freeinode = 1;
void wsect(uint, void *);
void winode(uint, struct dinode *);
void rsect(uint sec, void *buf);
uint ialloc(ushort type);
void iappend(uint inum, void *p, int n);
// convert to intel byte order
ushort
@ -44,27 +48,21 @@ xint(uint x)
main(int argc, char *argv[])
{
int i;
struct dinode din;
char dbuf[512];
uint bn;
int i, cc, fd;
uint bn, rootino, inum;
struct dirent de;
char buf[512];
if(argc != 2){
fprintf(stderr, "Usage: mkfs fs.img\n");
if(argc < 2){
fprintf(stderr, "Usage: mkfs fs.img files...\n");
exit(1);
}
if((512 % sizeof(struct dinode)) != 0){
fprintf(stderr, "sizeof(dinode) must divide 512\n");
exit(1);
}
if((512 % sizeof(struct dirent)) != 0){
fprintf(stderr, "sizeof(dirent) must divide 512\n");
exit(1);
}
assert((512 % sizeof(struct dinode)) == 0);
assert((512 % sizeof(struct dirent)) == 0);
fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
if(fd < 0){
fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
if(fsfd < 0){
perror(argv[1]);
exit(1);
}
@ -79,20 +77,38 @@ main(int argc, char *argv[])
wsect(1, &sb);
bzero(&din, sizeof(din));
din.type = xshort(T_DIR);
din.nlink = xshort(2);
din.size = xint(512);
bn = freeblock++;
din.addrs[0] = xint(bn);
winode(1, &din);
rootino = ialloc(T_DIR);
assert(rootino == 1);
bzero(dbuf, sizeof(dbuf));
((struct dirent *) dbuf)[0].inum = xshort(1);
strcpy(((struct dirent *) dbuf)[0].name, ".");
((struct dirent *) dbuf)[1].inum = xshort(1);
strcpy(((struct dirent *) dbuf)[1].name, "..");
wsect(bn, dbuf);
bzero(&de, sizeof(de));
de.inum = xshort(rootino);
strcpy(de.name, ".");
iappend(rootino, &de, sizeof(de));
bzero(&de, sizeof(de));
de.inum = xshort(rootino);
strcpy(de.name, "..");
iappend(rootino, &de, sizeof(de));
for(i = 2; i < argc; i++){
assert(index(argv[i], '/') == 0);
if((fd = open(argv[i], 0)) < 0){
perror(argv[i]);
exit(1);
}
inum = ialloc(T_FILE);
bzero(&de, sizeof(de));
de.inum = xshort(inum);
strncpy(de.name, argv[i], DIRSIZ);
iappend(rootino, &de, sizeof(de));
while((cc = read(fd, buf, sizeof(buf))) > 0)
iappend(inum, buf, cc);
close(fd);
}
exit(0);
}
@ -100,11 +116,11 @@ main(int argc, char *argv[])
void
wsect(uint sec, void *buf)
{
if(lseek(fd, sec * 512L, 0) != sec * 512L){
if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
perror("lseek");
exit(1);
}
if(write(fd, buf, 512) != 512){
if(write(fsfd, buf, 512) != 512){
perror("write");
exit(1);
}
@ -127,20 +143,80 @@ winode(uint inum, struct dinode *ip)
rsect(bn, buf);
dip = ((struct dinode *) buf) + (inum % IPB);
*dip = *ip;
printf("bn %d off %d\n",
bn, (unsigned)dip - (unsigned) buf);
wsect(bn, buf);
printf("wi %d size %d addrs %d %d...\n",
inum,
xint(dip->size),
xint(dip->addrs[0]),
xint(dip->addrs[1]));
}
void
rinode(uint inum, struct dinode *ip)
{
char buf[512];
uint bn;
struct dinode *dip;
bn = i2b(inum);
rsect(bn, buf);
dip = ((struct dinode *) buf) + (inum % IPB);
*ip = *dip;
}
void
rsect(uint sec, void *buf)
{
if(lseek(fd, sec * 512L, 0) != sec * 512L){
if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
perror("lseek");
exit(1);
}
if(read(fd, buf, 512) != 512){
if(read(fsfd, buf, 512) != 512){
perror("read");
exit(1);
}
}
uint
ialloc(ushort type)
{
uint inum = freeinode++;
struct dinode din;
bzero(&din, sizeof(din));
din.type = xshort(type);
din.nlink = xshort(1);
din.size = xint(0);
winode(inum, &din);
return inum;
}
#define min(a, b) ((a) < (b) ? (a) : (b))
void
iappend(uint inum, void *xp, int n)
{
char *p = (char *) xp;
uint fbn, off, n1;
struct dinode din;
char buf[512];
rinode(inum, &din);
off = xint(din.size);
while(n > 0){
fbn = off / 512;
assert(fbn < NDIRECT);
if(din.addrs[fbn] == 0)
din.addrs[fbn] = xint(freeblock++);
n1 = min(n, (fbn + 1) * 512 - off);
rsect(xint(din.addrs[fbn]), buf);
bcopy(p, buf + off - (fbn * 512), n1);
wsect(xint(din.addrs[fbn]), buf);
n -= n1;
off += n1;
p += n1;
}
din.size = xint(off);
winode(inum, &din);
}

3
proc.c
View file

@ -137,6 +137,9 @@ scheduler(void)
cprintf("start scheduler on cpu %d jmpbuf %p\n", cpu(), &cpus[cpu()].jmpbuf);
cpus[cpu()].lastproc = &proc[0];
if(cpus[cpu()].nlock != 0)
panic("holding locks at first entry to scheduler");
for(;;){
// Loop over process table looking for process to run.
acquire(&proc_table_lock);

100
syscall.c
View file

@ -10,6 +10,7 @@
#include "buf.h"
#include "fs.h"
#include "fsvar.h"
#include "elf.h"
/*
* User code makes a system call with INT T_SYSCALL.
@ -57,6 +58,21 @@ fetcharg(int argno, void *ip)
return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip);
}
// check that an entire string is valid in user space
int
checkstring(uint s)
{
char c;
while(1){
if(fetchbyte(curproc[cpu()], s, &c) < 0)
return -1;
if(c == '\0')
return 0;
s++;
}
}
int
putint(struct proc *p, uint addr, int x)
{
@ -224,6 +240,81 @@ sys_cons_puts(void)
return 0;
}
int
sys_exec(void)
{
struct proc *cp = curproc[cpu()];
uint arg0, sz;
int i;
struct inode *ip;
struct elfhdr elf;
struct proghdr ph;
if(fetcharg(0, &arg0) < 0)
return -1;
if(checkstring(arg0) < 0)
return -1;
ip = namei(cp->mem + arg0);
if(ip == 0)
return -1;
if(readi(ip, &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, &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;
// commit to the new image.
kfree(cp->mem, cp->sz);
cp->sz = sz;
cp->mem = kalloc(cp->sz);
for(i = 0; i < elf.phnum; i++){
if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph))
goto bad;
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 = cp->sz;
setupsegs(cp);
return 0;
bad:
cprintf("exec failed early\n");
iput(ip);
return -1;
bad2:
cprintf("exec failed late\n");
iput(ip);
proc_exit();
return 0;
}
int
sys_block(void)
{
@ -248,14 +339,14 @@ sys_block(void)
ip->type, ip->nlink, ip->size, ip->addrs[0]);
iput(ip);
ip = namei(".././//./../");
ip = namei(".././//./../usertests");
if(ip){
cprintf("namei: %d %d %d %d %d %d %d %d\n",
cprintf("namei(usertests): %d %d %d %d %d %d %d %d\n",
ip->dev, ip->inum, ip->count, ip->busy,
ip->type, ip->nlink, ip->size, ip->addrs[0]);
iput(ip);
} else {
cprintf("namei failed\n");
cprintf("namei(usertests) failed\n");
}
return 0;
@ -317,6 +408,9 @@ syscall(void)
case SYS_cons_puts:
ret = sys_cons_puts();
break;
case SYS_exec:
ret = sys_exec();
break;
default:
cprintf("unknown sys call %d\n", num);
// XXX fault

View file

@ -10,3 +10,4 @@
#define SYS_kill 10
#define SYS_panic 11
#define SYS_cons_puts 12
#define SYS_exec 13

View file

@ -9,5 +9,6 @@ main(void)
{
puts("userfs running\n");
block();
exec("usertests");
return 0;
}

1
usys.S
View file

@ -20,3 +20,4 @@ STUB(block)
STUB(kill)
STUB(panic)
STUB(cons_puts)
STUB(exec)