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
|
mkfs : mkfs.c fs.h
|
||||||
cc -o mkfs mkfs.c
|
cc -o mkfs mkfs.c
|
||||||
|
|
||||||
fs.img : mkfs
|
fs.img : mkfs usertests
|
||||||
./mkfs fs.img
|
./mkfs fs.img usertests
|
||||||
|
|
||||||
-include *.d
|
-include *.d
|
||||||
|
|
||||||
|
|
1
defs.h
1
defs.h
|
@ -102,3 +102,4 @@ void iunlock(struct inode *ip);
|
||||||
void iincref(struct inode *ip);
|
void iincref(struct inode *ip);
|
||||||
void iput(struct inode *ip);
|
void iput(struct inode *ip);
|
||||||
struct inode * namei(char *path);
|
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;
|
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 *
|
struct inode *
|
||||||
namei(char *path)
|
namei(char *path)
|
||||||
{
|
{
|
||||||
|
|
1
main.c
1
main.c
|
@ -100,6 +100,7 @@ mpmain(void)
|
||||||
lapic_enableintr();
|
lapic_enableintr();
|
||||||
|
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
|
cprintf("cpu %d initial nlock %d\n", cpu(), cpus[cpu()].nlock);
|
||||||
cpus[cpu()].nlock--;
|
cpus[cpu()].nlock--;
|
||||||
sti();
|
sti();
|
||||||
|
|
||||||
|
|
148
mkfs.c
148
mkfs.c
|
@ -3,6 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
@ -10,14 +11,17 @@
|
||||||
int nblocks = 1009;
|
int nblocks = 1009;
|
||||||
int ninodes = 100;
|
int ninodes = 100;
|
||||||
|
|
||||||
int fd;
|
int fsfd;
|
||||||
struct superblock sb;
|
struct superblock sb;
|
||||||
char zeroes[512];
|
char zeroes[512];
|
||||||
uint freeblock;
|
uint freeblock;
|
||||||
|
uint freeinode = 1;
|
||||||
|
|
||||||
void wsect(uint, void *);
|
void wsect(uint, void *);
|
||||||
void winode(uint, struct dinode *);
|
void winode(uint, struct dinode *);
|
||||||
void rsect(uint sec, void *buf);
|
void rsect(uint sec, void *buf);
|
||||||
|
uint ialloc(ushort type);
|
||||||
|
void iappend(uint inum, void *p, int n);
|
||||||
|
|
||||||
// convert to intel byte order
|
// convert to intel byte order
|
||||||
ushort
|
ushort
|
||||||
|
@ -44,27 +48,21 @@ xint(uint x)
|
||||||
|
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i, cc, fd;
|
||||||
struct dinode din;
|
uint bn, rootino, inum;
|
||||||
char dbuf[512];
|
struct dirent de;
|
||||||
uint bn;
|
char buf[512];
|
||||||
|
|
||||||
if(argc != 2){
|
if(argc < 2){
|
||||||
fprintf(stderr, "Usage: mkfs fs.img\n");
|
fprintf(stderr, "Usage: mkfs fs.img files...\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((512 % sizeof(struct dinode)) != 0){
|
assert((512 % sizeof(struct dinode)) == 0);
|
||||||
fprintf(stderr, "sizeof(dinode) must divide 512\n");
|
assert((512 % sizeof(struct dirent)) == 0);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if((512 % sizeof(struct dirent)) != 0){
|
|
||||||
fprintf(stderr, "sizeof(dirent) must divide 512\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
|
fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||||
if(fd < 0){
|
if(fsfd < 0){
|
||||||
perror(argv[1]);
|
perror(argv[1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -79,20 +77,38 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
wsect(1, &sb);
|
wsect(1, &sb);
|
||||||
|
|
||||||
bzero(&din, sizeof(din));
|
rootino = ialloc(T_DIR);
|
||||||
din.type = xshort(T_DIR);
|
assert(rootino == 1);
|
||||||
din.nlink = xshort(2);
|
|
||||||
din.size = xint(512);
|
|
||||||
bn = freeblock++;
|
|
||||||
din.addrs[0] = xint(bn);
|
|
||||||
winode(1, &din);
|
|
||||||
|
|
||||||
bzero(dbuf, sizeof(dbuf));
|
bzero(&de, sizeof(de));
|
||||||
((struct dirent *) dbuf)[0].inum = xshort(1);
|
de.inum = xshort(rootino);
|
||||||
strcpy(((struct dirent *) dbuf)[0].name, ".");
|
strcpy(de.name, ".");
|
||||||
((struct dirent *) dbuf)[1].inum = xshort(1);
|
iappend(rootino, &de, sizeof(de));
|
||||||
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));
|
||||||
|
|
||||||
|
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);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -100,11 +116,11 @@ main(int argc, char *argv[])
|
||||||
void
|
void
|
||||||
wsect(uint sec, void *buf)
|
wsect(uint sec, void *buf)
|
||||||
{
|
{
|
||||||
if(lseek(fd, sec * 512L, 0) != sec * 512L){
|
if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
|
||||||
perror("lseek");
|
perror("lseek");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(write(fd, buf, 512) != 512){
|
if(write(fsfd, buf, 512) != 512){
|
||||||
perror("write");
|
perror("write");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -127,20 +143,80 @@ winode(uint inum, struct dinode *ip)
|
||||||
rsect(bn, buf);
|
rsect(bn, buf);
|
||||||
dip = ((struct dinode *) buf) + (inum % IPB);
|
dip = ((struct dinode *) buf) + (inum % IPB);
|
||||||
*dip = *ip;
|
*dip = *ip;
|
||||||
printf("bn %d off %d\n",
|
|
||||||
bn, (unsigned)dip - (unsigned) buf);
|
|
||||||
wsect(bn, 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
|
void
|
||||||
rsect(uint sec, void *buf)
|
rsect(uint sec, void *buf)
|
||||||
{
|
{
|
||||||
if(lseek(fd, sec * 512L, 0) != sec * 512L){
|
if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
|
||||||
perror("lseek");
|
perror("lseek");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(read(fd, buf, 512) != 512){
|
if(read(fsfd, buf, 512) != 512){
|
||||||
perror("read");
|
perror("read");
|
||||||
exit(1);
|
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);
|
cprintf("start scheduler on cpu %d jmpbuf %p\n", cpu(), &cpus[cpu()].jmpbuf);
|
||||||
cpus[cpu()].lastproc = &proc[0];
|
cpus[cpu()].lastproc = &proc[0];
|
||||||
|
|
||||||
|
if(cpus[cpu()].nlock != 0)
|
||||||
|
panic("holding locks at first entry to scheduler");
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
// Loop over process table looking for process to run.
|
// Loop over process table looking for process to run.
|
||||||
acquire(&proc_table_lock);
|
acquire(&proc_table_lock);
|
||||||
|
|
100
syscall.c
100
syscall.c
|
@ -10,6 +10,7 @@
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "fsvar.h"
|
#include "fsvar.h"
|
||||||
|
#include "elf.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User code makes a system call with INT T_SYSCALL.
|
* 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);
|
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
|
int
|
||||||
putint(struct proc *p, uint addr, int x)
|
putint(struct proc *p, uint addr, int x)
|
||||||
{
|
{
|
||||||
|
@ -224,6 +240,81 @@ sys_cons_puts(void)
|
||||||
return 0;
|
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
|
int
|
||||||
sys_block(void)
|
sys_block(void)
|
||||||
{
|
{
|
||||||
|
@ -248,14 +339,14 @@ sys_block(void)
|
||||||
ip->type, ip->nlink, ip->size, ip->addrs[0]);
|
ip->type, ip->nlink, ip->size, ip->addrs[0]);
|
||||||
iput(ip);
|
iput(ip);
|
||||||
|
|
||||||
ip = namei(".././//./../");
|
ip = namei(".././//./../usertests");
|
||||||
if(ip){
|
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->dev, ip->inum, ip->count, ip->busy,
|
||||||
ip->type, ip->nlink, ip->size, ip->addrs[0]);
|
ip->type, ip->nlink, ip->size, ip->addrs[0]);
|
||||||
iput(ip);
|
iput(ip);
|
||||||
} else {
|
} else {
|
||||||
cprintf("namei failed\n");
|
cprintf("namei(usertests) failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -317,6 +408,9 @@ syscall(void)
|
||||||
case SYS_cons_puts:
|
case SYS_cons_puts:
|
||||||
ret = sys_cons_puts();
|
ret = sys_cons_puts();
|
||||||
break;
|
break;
|
||||||
|
case SYS_exec:
|
||||||
|
ret = sys_exec();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cprintf("unknown sys call %d\n", num);
|
cprintf("unknown sys call %d\n", num);
|
||||||
// XXX fault
|
// XXX fault
|
||||||
|
|
|
@ -10,3 +10,4 @@
|
||||||
#define SYS_kill 10
|
#define SYS_kill 10
|
||||||
#define SYS_panic 11
|
#define SYS_panic 11
|
||||||
#define SYS_cons_puts 12
|
#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");
|
puts("userfs running\n");
|
||||||
block();
|
block();
|
||||||
|
exec("usertests");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
1
usys.S
1
usys.S
|
@ -20,3 +20,4 @@ STUB(block)
|
||||||
STUB(kill)
|
STUB(kill)
|
||||||
STUB(panic)
|
STUB(panic)
|
||||||
STUB(cons_puts)
|
STUB(cons_puts)
|
||||||
|
STUB(exec)
|
||||||
|
|
Loading…
Reference in a new issue