Add execve syscall.
This commit is contained in:
parent
27951515a2
commit
fc4f8c56b2
12
Makefile
12
Makefile
|
@ -200,16 +200,14 @@ UPROGS=\
|
||||||
$U/_find\
|
$U/_find\
|
||||||
$U/_rm\
|
$U/_rm\
|
||||||
$U/_wc\
|
$U/_wc\
|
||||||
$U/_test\
|
$U/_info\
|
||||||
$U/_usertests\
|
$U/_usertests\
|
||||||
$U/_strace\
|
$U/_strace\
|
||||||
$U/_mv\
|
$U/_mv\
|
||||||
|
$U/_test\
|
||||||
# $U/_forktest\
|
$U/_grind\
|
||||||
# $U/_ln\
|
$U/_forktest\
|
||||||
# $U/_stressfs\
|
$U/_stressfs\
|
||||||
# $U/_grind\
|
|
||||||
# $U/_zombie\
|
|
||||||
|
|
||||||
userprogs: $(UPROGS)
|
userprogs: $(UPROGS)
|
||||||
|
|
||||||
|
|
173
kernel/exec.c
173
kernel/exec.c
|
@ -3,8 +3,6 @@
|
||||||
#include "include/param.h"
|
#include "include/param.h"
|
||||||
#include "include/memlayout.h"
|
#include "include/memlayout.h"
|
||||||
#include "include/riscv.h"
|
#include "include/riscv.h"
|
||||||
#include "include/spinlock.h"
|
|
||||||
#include "include/sleeplock.h"
|
|
||||||
#include "include/proc.h"
|
#include "include/proc.h"
|
||||||
#include "include/elf.h"
|
#include "include/elf.h"
|
||||||
#include "include/fat32.h"
|
#include "include/fat32.h"
|
||||||
|
@ -12,6 +10,7 @@
|
||||||
#include "include/vm.h"
|
#include "include/vm.h"
|
||||||
#include "include/printf.h"
|
#include "include/printf.h"
|
||||||
#include "include/string.h"
|
#include "include/string.h"
|
||||||
|
#include "include/syscall.h"
|
||||||
|
|
||||||
// Load a program segment into pagetable at virtual address va.
|
// Load a program segment into pagetable at virtual address va.
|
||||||
// va must be page-aligned
|
// va must be page-aligned
|
||||||
|
@ -40,30 +39,17 @@ loadseg(pagetable_t pagetable, uint64 va, struct dirent *ep, uint offset, uint s
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All argvs are pointers came from user space, and should be checked by sys_caller
|
||||||
int exec(char *path, char **argv)
|
int execve(char *path, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
char *s, *last;
|
struct dirent *ep = NULL;
|
||||||
int i, off;
|
pagetable_t pagetable = NULL;
|
||||||
uint64 argc, sz = 0, sp, ustack[MAXARG+1], stackbase;
|
pagetable_t kpagetable = NULL;
|
||||||
struct elfhdr elf;
|
char *buf = NULL;
|
||||||
struct dirent *ep;
|
|
||||||
struct proghdr ph;
|
|
||||||
pagetable_t pagetable = 0, oldpagetable;
|
|
||||||
pagetable_t kpagetable = 0, oldkpagetable;
|
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
|
|
||||||
// Make a copy of p->kpt without old user space,
|
if ((buf = kalloc()) == NULL || copyinstr2(buf, (uint64)path, FAT32_MAX_PATH) < 0
|
||||||
// but with the same kstack we are using now, which can't be changed
|
|| (ep = ename(buf)) == NULL) {
|
||||||
if ((kpagetable = (pagetable_t)kalloc()) == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memmove(kpagetable, p->kpagetable, PGSIZE);
|
|
||||||
for (int i = 0; i < PX(2, MAXUVA); i++) {
|
|
||||||
kpagetable[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((ep = ename(path)) == NULL) {
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("[exec] %s not found\n", path);
|
printf("[exec] %s not found\n", path);
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,70 +58,114 @@ int exec(char *path, char **argv)
|
||||||
elock(ep);
|
elock(ep);
|
||||||
|
|
||||||
// Check ELF header
|
// Check ELF header
|
||||||
if(eread(ep, 0, (uint64) &elf, 0, sizeof(elf)) != sizeof(elf))
|
struct elfhdr elf;
|
||||||
|
if (eread(ep, 0, (uint64) &elf, 0, sizeof(elf)) != sizeof(elf))
|
||||||
goto bad;
|
goto bad;
|
||||||
if(elf.magic != ELF_MAGIC)
|
if (elf.magic != ELF_MAGIC)
|
||||||
goto bad;
|
|
||||||
if((pagetable = proc_pagetable(p)) == NULL)
|
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
|
// Make a copy of p->kpt without old user space,
|
||||||
|
// but with the same kstack we are using now, which can't be changed.
|
||||||
// Load program into memory.
|
// Load program into memory.
|
||||||
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
|
uint64 sz = 0;
|
||||||
if(eread(ep, 0, (uint64)&ph, off, sizeof(ph)) != sizeof(ph))
|
if ((pagetable = proc_pagetable(p)) == NULL)
|
||||||
|
goto bad;
|
||||||
|
if ((kpagetable = (pagetable_t)kalloc()) == NULL)
|
||||||
|
goto bad;
|
||||||
|
memmove(kpagetable, p->kpagetable, PGSIZE);
|
||||||
|
for (int i = 0; i < PX(2, MAXUVA); i++) {
|
||||||
|
kpagetable[i] = 0;
|
||||||
|
}
|
||||||
|
struct proghdr ph;
|
||||||
|
for (int i = 0, off = elf.phoff; i < elf.phnum; i++, off += sizeof(ph)) {
|
||||||
|
if (eread(ep, 0, (uint64)&ph, off, sizeof(ph)) != sizeof(ph))
|
||||||
goto bad;
|
goto bad;
|
||||||
if(ph.type != ELF_PROG_LOAD)
|
if (ph.type != ELF_PROG_LOAD)
|
||||||
continue;
|
continue;
|
||||||
if(ph.memsz < ph.filesz)
|
if (ph.memsz < ph.filesz)
|
||||||
goto bad;
|
goto bad;
|
||||||
if(ph.vaddr + ph.memsz < ph.vaddr)
|
if (ph.vaddr + ph.memsz < ph.vaddr)
|
||||||
goto bad;
|
goto bad;
|
||||||
uint64 sz1;
|
uint64 sz1;
|
||||||
if((sz1 = uvmalloc(pagetable, kpagetable, sz, ph.vaddr + ph.memsz)) == 0)
|
if ((sz1 = uvmalloc(pagetable, kpagetable, sz, ph.vaddr + ph.memsz)) == 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
sz = sz1;
|
sz = sz1;
|
||||||
if(ph.vaddr % PGSIZE != 0)
|
if (ph.vaddr % PGSIZE != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
if(loadseg(pagetable, ph.vaddr, ep, ph.off, ph.filesz) < 0)
|
if (loadseg(pagetable, ph.vaddr, ep, ph.off, ph.filesz) < 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
char pname[16];
|
||||||
|
safestrcpy(pname, ep->filename, sizeof(pname));
|
||||||
eunlock(ep);
|
eunlock(ep);
|
||||||
eput(ep);
|
eput(ep);
|
||||||
ep = 0;
|
ep = 0;
|
||||||
|
|
||||||
p = myproc();
|
|
||||||
uint64 oldsz = p->sz;
|
|
||||||
|
|
||||||
// Allocate two pages at the next page boundary.
|
// Allocate two pages at the next page boundary.
|
||||||
// Use the second as the user stack.
|
// Use the second as the user stack.
|
||||||
sz = PGROUNDUP(sz);
|
sz = PGROUNDUP(sz);
|
||||||
uint64 sz1;
|
uint64 sz1;
|
||||||
if((sz1 = uvmalloc(pagetable, kpagetable, sz, sz + 2*PGSIZE)) == 0)
|
if ((sz1 = uvmalloc(pagetable, kpagetable, sz, sz + 2 * PGSIZE)) == 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
sz = sz1;
|
sz = sz1;
|
||||||
uvmclear(pagetable, sz-2*PGSIZE);
|
uvmclear(pagetable, sz - 2 * PGSIZE);
|
||||||
sp = sz;
|
uint64 sp = sz;
|
||||||
stackbase = sp - PGSIZE;
|
uint64 stackbase = sp - PGSIZE;
|
||||||
|
sp -= sizeof(uint64);
|
||||||
// Push argument strings, prepare rest of stack in ustack.
|
if (copyout(pagetable, sp, (char *)&ep, sizeof(uint64)) < 0) // *ep is 0 now, borrow it
|
||||||
for(argc = 0; argv[argc]; argc++) {
|
|
||||||
if(argc >= MAXARG)
|
|
||||||
goto bad;
|
|
||||||
sp -= strlen(argv[argc]) + 1;
|
|
||||||
sp -= sp % 16; // riscv sp must be 16-byte aligned
|
|
||||||
if(sp < stackbase)
|
|
||||||
goto bad;
|
|
||||||
if(copyout(pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
|
|
||||||
goto bad;
|
|
||||||
ustack[argc] = sp;
|
|
||||||
}
|
|
||||||
ustack[argc] = 0;
|
|
||||||
|
|
||||||
// push the array of argv[] pointers.
|
|
||||||
sp -= (argc+1) * sizeof(uint64);
|
|
||||||
sp -= sp % 16;
|
|
||||||
if(sp < stackbase)
|
|
||||||
goto bad;
|
goto bad;
|
||||||
if(copyout(pagetable, sp, (char *)ustack, (argc+1)*sizeof(uint64)) < 0)
|
|
||||||
|
// Push env strings
|
||||||
|
uint64 argc = 0, envc = 0, uargv[MAXARG + 1], uenvp[MAXENV + 1], argp;
|
||||||
|
while (envp) {
|
||||||
|
if (envc >= MAXENV || fetchaddr((uint64)(envp + envc), &argp) < 0)
|
||||||
|
goto bad;
|
||||||
|
if (argp == 0)
|
||||||
|
break;
|
||||||
|
int envlen = fetchstr(argp, buf, PGSIZE); // '\0' included in PGSIZE, but not in envlen
|
||||||
|
if (envlen++ < 0) // including '\0'
|
||||||
|
goto bad;
|
||||||
|
sp -= envlen;
|
||||||
|
sp -= sp % 16;
|
||||||
|
if (sp < stackbase)
|
||||||
|
goto bad;
|
||||||
|
if (copyout(pagetable, sp, buf, envlen) < 0)
|
||||||
|
goto bad;
|
||||||
|
uenvp[envc++] = sp;
|
||||||
|
}
|
||||||
|
uenvp[envc] = 0;
|
||||||
|
// Push envp[] table
|
||||||
|
sp -= (envc + 1) * sizeof(uint64);
|
||||||
|
sp -= sp % 16;
|
||||||
|
if (sp < stackbase)
|
||||||
|
goto bad;
|
||||||
|
if (copyout(pagetable, sp, (char *)uenvp, (envc + 1) * sizeof(uint64)) < 0)
|
||||||
|
goto bad;
|
||||||
|
p->trapframe->a2 = sp;
|
||||||
|
// Push argument strings, prepare rest of stack in ustack.
|
||||||
|
while (argv) {
|
||||||
|
if (argc >= MAXARG || fetchaddr((uint64)(argv + argc), &argp) < 0)
|
||||||
|
goto bad;
|
||||||
|
if (argp == 0)
|
||||||
|
break;
|
||||||
|
int argvlen = fetchstr(argp, buf, PGSIZE);
|
||||||
|
if (argvlen++ < 0)
|
||||||
|
goto bad;
|
||||||
|
sp -= argvlen;
|
||||||
|
sp -= sp % 16; // riscv sp must be 16-byte aligned
|
||||||
|
if (sp < stackbase)
|
||||||
|
goto bad;
|
||||||
|
if (copyout(pagetable, sp, buf, argvlen) < 0)
|
||||||
|
goto bad;
|
||||||
|
uargv[argc++] = sp;
|
||||||
|
}
|
||||||
|
uargv[argc] = 0;
|
||||||
|
// push the array of argv[] pointers.
|
||||||
|
sp -= (argc + 1) * sizeof(uint64);
|
||||||
|
sp -= sp % 16;
|
||||||
|
if (sp < stackbase)
|
||||||
|
goto bad;
|
||||||
|
if (copyout(pagetable, sp, (char *)uargv, (argc + 1) * sizeof(uint64)) < 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
// arguments to user main(argc, argv)
|
// arguments to user main(argc, argv)
|
||||||
|
@ -144,19 +174,18 @@ int exec(char *path, char **argv)
|
||||||
p->trapframe->a1 = sp;
|
p->trapframe->a1 = sp;
|
||||||
|
|
||||||
// Save program name for debugging.
|
// Save program name for debugging.
|
||||||
for(last=s=path; *s; s++)
|
memmove(p->name, pname, sizeof(p->name));
|
||||||
if(*s == '/')
|
|
||||||
last = s+1;
|
|
||||||
safestrcpy(p->name, last, sizeof(p->name));
|
|
||||||
|
|
||||||
// Commit to the user image.
|
// Commit to the user image.
|
||||||
oldpagetable = p->pagetable;
|
pagetable_t oldpagetable = p->pagetable;
|
||||||
oldkpagetable = p->kpagetable;
|
pagetable_t oldkpagetable = p->kpagetable;
|
||||||
|
uint64 oldsz = p->sz;
|
||||||
p->pagetable = pagetable;
|
p->pagetable = pagetable;
|
||||||
p->kpagetable = kpagetable;
|
p->kpagetable = kpagetable;
|
||||||
p->sz = sz;
|
p->sz = sz;
|
||||||
p->trapframe->epc = elf.entry; // initial program counter = main
|
p->trapframe->epc = elf.entry; // initial program counter = main
|
||||||
p->trapframe->sp = sp; // initial stack pointer
|
p->trapframe->sp = sp; // initial stack pointer
|
||||||
|
kfree(buf);
|
||||||
proc_freepagetable(oldpagetable, oldsz);
|
proc_freepagetable(oldpagetable, oldsz);
|
||||||
w_satp(MAKE_SATP(p->kpagetable));
|
w_satp(MAKE_SATP(p->kpagetable));
|
||||||
sfence_vma();
|
sfence_vma();
|
||||||
|
@ -167,11 +196,13 @@ int exec(char *path, char **argv)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("[exec] reach bad\n");
|
printf("[exec] reach bad\n");
|
||||||
#endif
|
#endif
|
||||||
if(pagetable)
|
if (buf)
|
||||||
|
kfree(buf);
|
||||||
|
if (pagetable)
|
||||||
proc_freepagetable(pagetable, sz);
|
proc_freepagetable(pagetable, sz);
|
||||||
if(kpagetable)
|
if (kpagetable)
|
||||||
kvmfree(kpagetable, 0);
|
kvmfree(kpagetable, 0);
|
||||||
if(ep){
|
if (ep) {
|
||||||
eunlock(ep);
|
eunlock(ep);
|
||||||
eput(ep);
|
eput(ep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -570,8 +570,7 @@ struct dirent *ealloc(struct dirent *dp, char *name, int attr)
|
||||||
ep->clus_cnt = 0;
|
ep->clus_cnt = 0;
|
||||||
ep->cur_clus = 0;
|
ep->cur_clus = 0;
|
||||||
ep->dirty = 0;
|
ep->dirty = 0;
|
||||||
strncpy(ep->filename, name, FAT32_MAX_FILENAME);
|
safestrcpy(ep->filename, name, FAT32_MAX_FILENAME);
|
||||||
ep->filename[FAT32_MAX_FILENAME] = '\0';
|
|
||||||
if (attr == ATTR_DIRECTORY) { // generate "." and ".." for ep
|
if (attr == ATTR_DIRECTORY) { // generate "." and ".." for ep
|
||||||
ep->attribute |= ATTR_DIRECTORY;
|
ep->attribute |= ATTR_DIRECTORY;
|
||||||
ep->cur_clus = ep->first_clus = alloc_clus(dp->dev);
|
ep->cur_clus = ep->first_clus = alloc_clus(dp->dev);
|
||||||
|
@ -588,11 +587,9 @@ struct dirent *ealloc(struct dirent *dp, char *name, int attr)
|
||||||
|
|
||||||
struct dirent *edup(struct dirent *entry)
|
struct dirent *edup(struct dirent *entry)
|
||||||
{
|
{
|
||||||
if (entry != 0) {
|
acquire(&ecache.lock);
|
||||||
acquire(&ecache.lock);
|
entry->ref++;
|
||||||
entry->ref++;
|
release(&ecache.lock);
|
||||||
release(&ecache.lock);
|
|
||||||
}
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#define NDEV 10 // maximum major device number
|
#define NDEV 10 // maximum major device number
|
||||||
#define ROOTDEV 1 // device number of file system root disk
|
#define ROOTDEV 1 // device number of file system root disk
|
||||||
#define MAXARG 32 // max exec arguments
|
#define MAXARG 32 // max exec arguments
|
||||||
|
#define MAXENV 8 // max execve envs
|
||||||
#define MAXOPBLOCKS 10 // max # of blocks any FS op writes
|
#define MAXOPBLOCKS 10 // max # of blocks any FS op writes
|
||||||
#define LOGSIZE (MAXOPBLOCKS*3) // max data blocks in on-disk log
|
#define LOGSIZE (MAXOPBLOCKS*3) // max data blocks in on-disk log
|
||||||
#define NBUF (MAXOPBLOCKS*3) // size of disk block cache
|
#define NBUF (MAXOPBLOCKS*3) // size of disk block cache
|
||||||
|
|
|
@ -28,5 +28,6 @@
|
||||||
#define SYS_readdir 24
|
#define SYS_readdir 24
|
||||||
#define SYS_getcwd 25
|
#define SYS_getcwd 25
|
||||||
#define SYS_rename 26
|
#define SYS_rename 26
|
||||||
|
#define SYS_execve 27
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -116,6 +116,7 @@ extern uint64 sys_remove(void);
|
||||||
extern uint64 sys_trace(void);
|
extern uint64 sys_trace(void);
|
||||||
extern uint64 sys_sysinfo(void);
|
extern uint64 sys_sysinfo(void);
|
||||||
extern uint64 sys_rename(void);
|
extern uint64 sys_rename(void);
|
||||||
|
extern uint64 sys_execve(void);
|
||||||
|
|
||||||
static uint64 (*syscalls[])(void) = {
|
static uint64 (*syscalls[])(void) = {
|
||||||
[SYS_fork] sys_fork,
|
[SYS_fork] sys_fork,
|
||||||
|
@ -144,6 +145,7 @@ static uint64 (*syscalls[])(void) = {
|
||||||
[SYS_trace] sys_trace,
|
[SYS_trace] sys_trace,
|
||||||
[SYS_sysinfo] sys_sysinfo,
|
[SYS_sysinfo] sys_sysinfo,
|
||||||
[SYS_rename] sys_rename,
|
[SYS_rename] sys_rename,
|
||||||
|
[SYS_execve] sys_execve,
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *sysnames[] = {
|
static char *sysnames[] = {
|
||||||
|
@ -173,6 +175,7 @@ static char *sysnames[] = {
|
||||||
[SYS_trace] "trace",
|
[SYS_trace] "trace",
|
||||||
[SYS_sysinfo] "sysinfo",
|
[SYS_sysinfo] "sysinfo",
|
||||||
[SYS_rename] "rename",
|
[SYS_rename] "rename",
|
||||||
|
[SYS_execve] "execve",
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -11,48 +11,67 @@
|
||||||
#include "include/string.h"
|
#include "include/string.h"
|
||||||
#include "include/printf.h"
|
#include "include/printf.h"
|
||||||
|
|
||||||
extern int exec(char *path, char **argv);
|
extern int execve(char *path, char **argv, char **envp);
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
sys_exec(void)
|
sys_exec(void)
|
||||||
{
|
{
|
||||||
char path[FAT32_MAX_PATH], *argv[MAXARG];
|
uint64 path, argv;
|
||||||
int i;
|
|
||||||
uint64 uargv, uarg;
|
|
||||||
|
|
||||||
if(argstr(0, path, FAT32_MAX_PATH) < 0 || argaddr(1, &uargv) < 0){
|
if(argaddr(0, &path) < 0 || argaddr(1, &argv) < 0){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(argv, 0, sizeof(argv));
|
|
||||||
for(i=0;; i++){
|
return execve((char *)path, (char **)argv, 0);
|
||||||
if(i >= NELEM(argv)){
|
// char path[FAT32_MAX_PATH], *argv[MAXARG];
|
||||||
goto bad;
|
// int i;
|
||||||
}
|
// uint64 uargv, uarg;
|
||||||
if(fetchaddr(uargv+sizeof(uint64)*i, (uint64*)&uarg) < 0){
|
|
||||||
goto bad;
|
// if(argstr(0, path, FAT32_MAX_PATH) < 0 || argaddr(1, &uargv) < 0){
|
||||||
}
|
// return -1;
|
||||||
if(uarg == 0){
|
// }
|
||||||
argv[i] = 0;
|
// memset(argv, 0, sizeof(argv));
|
||||||
break;
|
// for(i=0;; i++){
|
||||||
}
|
// if(i >= NELEM(argv)){
|
||||||
argv[i] = kalloc();
|
// goto bad;
|
||||||
if(argv[i] == 0)
|
// }
|
||||||
goto bad;
|
// if(fetchaddr(uargv+sizeof(uint64)*i, (uint64*)&uarg) < 0){
|
||||||
if(fetchstr(uarg, argv[i], PGSIZE) < 0)
|
// goto bad;
|
||||||
goto bad;
|
// }
|
||||||
|
// if(uarg == 0){
|
||||||
|
// argv[i] = 0;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// argv[i] = kalloc();
|
||||||
|
// if(argv[i] == 0)
|
||||||
|
// goto bad;
|
||||||
|
// if(fetchstr(uarg, argv[i], PGSIZE) < 0)
|
||||||
|
// goto bad;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int ret = execve(path, argv, 0);
|
||||||
|
|
||||||
|
// for(i = 0; i < NELEM(argv) && argv[i] != 0; i++)
|
||||||
|
// kfree(argv[i]);
|
||||||
|
|
||||||
|
// return ret;
|
||||||
|
|
||||||
|
// bad:
|
||||||
|
// for(i = 0; i < NELEM(argv) && argv[i] != 0; i++)
|
||||||
|
// kfree(argv[i]);
|
||||||
|
// return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64
|
||||||
|
sys_execve(void)
|
||||||
|
{
|
||||||
|
uint64 path, argv, envp;
|
||||||
|
|
||||||
|
if(argaddr(0, &path) < 0 || argaddr(1, &argv) < 0 || argaddr(2, &envp)){
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = exec(path, argv);
|
return execve((char *)path, (char **)argv, (char **)envp);
|
||||||
|
|
||||||
for(i = 0; i < NELEM(argv) && argv[i] != 0; i++)
|
|
||||||
kfree(argv[i]);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
for(i = 0; i < NELEM(argv) && argv[i] != 0; i++)
|
|
||||||
kfree(argv[i]);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "kernel/include/types.h"
|
#include "kernel/include/types.h"
|
||||||
#include "kernel/include/stat.h"
|
#include "kernel/include/stat.h"
|
||||||
#include "xv6-user/user.h"
|
#include "xv6-user/user.h"
|
||||||
#include "kernel/include/fs.h"
|
|
||||||
#include "kernel/include/fcntl.h"
|
#include "kernel/include/fcntl.h"
|
||||||
#include "kernel/include/syscall.h"
|
#include "kernel/include/syscall.h"
|
||||||
#include "kernel/include/memlayout.h"
|
#include "kernel/include/memlayout.h"
|
||||||
|
@ -72,13 +71,15 @@ go(int which_child)
|
||||||
} else if(what == 2){
|
} else if(what == 2){
|
||||||
close(open("grindir/../grindir/../b", O_CREATE|O_RDWR));
|
close(open("grindir/../grindir/../b", O_CREATE|O_RDWR));
|
||||||
} else if(what == 3){
|
} else if(what == 3){
|
||||||
unlink("grindir/../a");
|
// unlink("grindir/../a");
|
||||||
|
remove("grindir/../a");
|
||||||
} else if(what == 4){
|
} else if(what == 4){
|
||||||
if(chdir("grindir") != 0){
|
if(chdir("grindir") != 0){
|
||||||
printf("chdir grindir failed\n");
|
printf("chdir grindir failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
unlink("../b");
|
// unlink("../b");
|
||||||
|
remove("../b");
|
||||||
chdir("/");
|
chdir("/");
|
||||||
} else if(what == 5){
|
} else if(what == 5){
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -93,17 +94,19 @@ go(int which_child)
|
||||||
} else if(what == 9){
|
} else if(what == 9){
|
||||||
mkdir("grindir/../a");
|
mkdir("grindir/../a");
|
||||||
close(open("a/../a/./a", O_CREATE|O_RDWR));
|
close(open("a/../a/./a", O_CREATE|O_RDWR));
|
||||||
unlink("a/a");
|
// unlink("a/a");
|
||||||
|
remove("a/a");
|
||||||
} else if(what == 10){
|
} else if(what == 10){
|
||||||
mkdir("/../b");
|
mkdir("/../b");
|
||||||
close(open("grindir/../b/b", O_CREATE|O_RDWR));
|
close(open("grindir/../b/b", O_CREATE|O_RDWR));
|
||||||
unlink("b/b");
|
// unlink("b/b");
|
||||||
|
remove("b/b");
|
||||||
} else if(what == 11){
|
} else if(what == 11){
|
||||||
unlink("b");
|
// unlink("b");
|
||||||
link("../grindir/./../a", "../b");
|
// link("../grindir/./../a", "../b");
|
||||||
} else if(what == 12){
|
} else if(what == 12){
|
||||||
unlink("../grindir/../a");
|
// unlink("../grindir/../a");
|
||||||
link(".././b", "/grindir/../a");
|
// link(".././b", "/grindir/../a");
|
||||||
} else if(what == 13){
|
} else if(what == 13){
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
|
@ -180,12 +183,15 @@ go(int which_child)
|
||||||
} else if(what == 20){
|
} else if(what == 20){
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
unlink("a");
|
// unlink("a");
|
||||||
|
remove("a");
|
||||||
mkdir("a");
|
mkdir("a");
|
||||||
chdir("a");
|
chdir("a");
|
||||||
unlink("../a");
|
// unlink("../a");
|
||||||
|
remove("../a");
|
||||||
fd = open("x", O_CREATE|O_RDWR);
|
fd = open("x", O_CREATE|O_RDWR);
|
||||||
unlink("x");
|
// unlink("x");
|
||||||
|
remove("x");
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if(pid < 0){
|
} else if(pid < 0){
|
||||||
printf("fork failed\n");
|
printf("fork failed\n");
|
||||||
|
@ -193,7 +199,8 @@ go(int which_child)
|
||||||
}
|
}
|
||||||
wait(0);
|
wait(0);
|
||||||
} else if(what == 21){
|
} else if(what == 21){
|
||||||
unlink("c");
|
// unlink("c");
|
||||||
|
remove("c");
|
||||||
// should always succeed. check that there are free i-nodes,
|
// should always succeed. check that there are free i-nodes,
|
||||||
// file descriptors, blocks.
|
// file descriptors, blocks.
|
||||||
int fd1 = open("c", O_CREATE|O_RDWR);
|
int fd1 = open("c", O_CREATE|O_RDWR);
|
||||||
|
@ -214,12 +221,13 @@ go(int which_child)
|
||||||
printf("fstat reports wrong size %d\n", (int)st.size);
|
printf("fstat reports wrong size %d\n", (int)st.size);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(st.ino > 200){
|
// if(st.ino > 200){
|
||||||
printf("fstat reports crazy i-number %d\n", st.ino);
|
// printf("fstat reports crazy i-number %d\n", st.ino);
|
||||||
exit(1);
|
// exit(1);
|
||||||
}
|
// }
|
||||||
close(fd1);
|
close(fd1);
|
||||||
unlink("c");
|
// unlink("c");
|
||||||
|
remove("c");
|
||||||
} else if(what == 22){
|
} else if(what == 22){
|
||||||
// echo hi | cat
|
// echo hi | cat
|
||||||
int aa[2], bb[2];
|
int aa[2], bb[2];
|
||||||
|
@ -295,8 +303,10 @@ go(int which_child)
|
||||||
void
|
void
|
||||||
iter()
|
iter()
|
||||||
{
|
{
|
||||||
unlink("a");
|
// unlink("a");
|
||||||
unlink("b");
|
// unlink("b");
|
||||||
|
remove("a");
|
||||||
|
remove("b");
|
||||||
|
|
||||||
int pid1 = fork();
|
int pid1 = fork();
|
||||||
if(pid1 < 0){
|
if(pid1 < 0){
|
||||||
|
@ -335,15 +345,18 @@ iter()
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
while(1){
|
if (fork() == 0) {
|
||||||
int pid = fork();
|
while(1){
|
||||||
if(pid == 0){
|
int pid = fork();
|
||||||
iter();
|
if(pid == 0){
|
||||||
exit(0);
|
iter();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if(pid > 0){
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
sleep(20);
|
||||||
}
|
}
|
||||||
if(pid > 0){
|
|
||||||
wait(0);
|
|
||||||
}
|
|
||||||
sleep(20);
|
|
||||||
}
|
}
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include "kernel/include/types.h"
|
||||||
|
#include "kernel/include/stat.h"
|
||||||
|
#include "kernel/include/sysinfo.h"
|
||||||
|
#include "xv6-user/user.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct sysinfo info;
|
||||||
|
if (sysinfo(&info) < 0) {
|
||||||
|
printf("sysinfo fail!\n");
|
||||||
|
} else {
|
||||||
|
printf("memory left: %d KB\n", info.freemem >> 10);
|
||||||
|
printf("process amount: %d\n", info.nproc);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
#include "kernel/include/types.h"
|
|
||||||
#include "kernel/include/stat.h"
|
|
||||||
#include "xv6-user/user.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if(argc != 3){
|
|
||||||
fprintf(2, "Usage: ln old new\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if(link(argv[1], argv[2]) < 0)
|
|
||||||
fprintf(2, "link %s %s: failed\n", argv[1], argv[2]);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include "kernel/include/types.h"
|
#include "kernel/include/types.h"
|
||||||
#include "kernel/include/stat.h"
|
#include "kernel/include/stat.h"
|
||||||
#include "xv6-user/user.h"
|
#include "xv6-user/user.h"
|
||||||
#include "kernel/include/fs.h"
|
|
||||||
#include "kernel/include/fcntl.h"
|
#include "kernel/include/fcntl.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -1,16 +1,28 @@
|
||||||
#include "kernel/include/types.h"
|
#include "user.h"
|
||||||
#include "kernel/include/stat.h"
|
|
||||||
#include "kernel/include/sysinfo.h"
|
|
||||||
#include "xv6-user/user.h"
|
|
||||||
|
|
||||||
int main()
|
char *myenvp[] = {
|
||||||
|
"PATH=/bin",
|
||||||
|
"env1=xxx",
|
||||||
|
"env2=yyy",
|
||||||
|
"env3=zzz",
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[], char *envp[])
|
||||||
{
|
{
|
||||||
struct sysinfo info;
|
printf("argc: %d\n", argc);
|
||||||
if (sysinfo(&info) < 0) {
|
for (int i = 0; i < argc; i++) {
|
||||||
printf("sysinfo fail!\n");
|
printf("arg%d: [%s]\n", i, argv[i]);
|
||||||
} else {
|
}
|
||||||
printf("memory left: %d KB\n", info.freemem >> 10);
|
for (int i = 0; envp[i]; i++) {
|
||||||
printf("process amount: %d\n", info.nproc);
|
printf("env%d: [%s]\n", i, envp[i]);
|
||||||
|
}
|
||||||
|
int fk = 0;
|
||||||
|
if (argc > 1) {
|
||||||
|
fk = atoi(argv[1]);
|
||||||
|
}
|
||||||
|
if (fk && fork() == 0) {
|
||||||
|
strcpy(argv[1], "0");
|
||||||
|
execve("test", argv, myenvp);
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ int read(int fd, void *buf, int len);
|
||||||
int close(int fd);
|
int close(int fd);
|
||||||
int kill(int pid);
|
int kill(int pid);
|
||||||
int exec(char*, char**);
|
int exec(char*, char**);
|
||||||
|
int execve(char *name, char *argv[], char *envp[]);
|
||||||
int open(const char *filename, int mode);
|
int open(const char *filename, int mode);
|
||||||
int fstat(int fd, struct stat*);
|
int fstat(int fd, struct stat*);
|
||||||
int mkdir(const char *dirname);
|
int mkdir(const char *dirname);
|
||||||
|
|
|
@ -41,3 +41,4 @@ entry("remove");
|
||||||
entry("trace");
|
entry("trace");
|
||||||
entry("sysinfo");
|
entry("sysinfo");
|
||||||
entry("rename");
|
entry("rename");
|
||||||
|
entry("execve");
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
// Create a zombie process that
|
|
||||||
// must be reparented at exit.
|
|
||||||
|
|
||||||
#include "kernel/include/types.h"
|
|
||||||
#include "kernel/include/stat.h"
|
|
||||||
#include "xv6-user/user.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
main(void)
|
|
||||||
{
|
|
||||||
if(fork() > 0)
|
|
||||||
sleep(5); // Let child exit before parent.
|
|
||||||
exit(0);
|
|
||||||
}
|
|
Loading…
Reference in New Issue