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