primitive exec
This commit is contained in:
parent
54a4b00346
commit
c59361f143
10 changed files with 242 additions and 41 deletions
4
Makefile
4
Makefile
|
@ -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
1
defs.h
|
@ -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
23
fs.c
|
@ -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
1
main.c
|
@ -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
148
mkfs.c
|
@ -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
3
proc.c
|
@ -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
100
syscall.c
|
@ -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
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
#define SYS_kill 10
|
||||
#define SYS_panic 11
|
||||
#define SYS_cons_puts 12
|
||||
#define SYS_exec 13
|
||||
|
|
1
userfs.c
1
userfs.c
|
@ -9,5 +9,6 @@ main(void)
|
|||
{
|
||||
puts("userfs running\n");
|
||||
block();
|
||||
exec("usertests");
|
||||
return 0;
|
||||
}
|
||||
|
|
1
usys.S
1
usys.S
|
@ -20,3 +20,4 @@ STUB(block)
|
|||
STUB(kill)
|
||||
STUB(panic)
|
||||
STUB(cons_puts)
|
||||
STUB(exec)
|
||||
|
|
Loading…
Reference in a new issue