diff --git a/Makefile b/Makefile index 01ca1ff..819878a 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ OBJS = \ uart.o\ vectors.o\ vm.o\ + procfs.o\ # Cross-compiling (e.g., on Mac OS X) # TOOLPREFIX = i386-jos-elf @@ -215,6 +216,9 @@ QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS) -m 512 $(QEMUEXTRA) qemu: fs.img xv6.img $(QEMU) -serial mon:stdio $(QEMUOPTS) +qemu2: fs.img xv6.img + $(QEMU) -serial mon:stdio $(QEMUOPTS) -s -S + qemu-memfs: xv6memfs.img $(QEMU) xv6memfs.img -smp $(CPUS) -m 256 diff --git a/defs.h b/defs.h index ed314f0..7edf604 100644 --- a/defs.h +++ b/defs.h @@ -54,6 +54,10 @@ int fs_readi(struct inode*, char*, uint, uint); int fs_writei(struct inode*, char*, uint, uint); void fs_ipopulate(struct inode* ip); void fs_iupdate(struct inode*); +int procfs_readi(struct inode*, char*, uint, uint); +int procfs_writei(struct inode*, char*, uint, uint); +void procfs_ipopulate(struct inode* ip); +void procfs_iupdate(struct inode*); diff --git a/file.h b/file.h index 00e9472..ec0895c 100644 --- a/file.h +++ b/file.h @@ -42,6 +42,7 @@ struct inode { short minor; short nlink; uint size; + uint mounted; //mounted on non-default file system uint addrs[NDIRECT+1]; }; #define I_BUSY 0x1 diff --git a/fs.c b/fs.c index 06c2164..630abeb 100644 --- a/fs.c +++ b/fs.c @@ -27,6 +27,7 @@ static void itrunc(struct inode*); struct inode_functions fs_i_func = { fs_ipopulate, fs_iupdate, fs_readi, fs_writei }; + // Read the super block. void readsb(int dev, struct superblock *sb) @@ -171,7 +172,8 @@ iinit(void) initlock(&icache.lock, "icache"); } -static struct inode* iget(uint dev, uint inum, struct inode* parent); + +struct inode* iget(uint dev, uint inum, struct inode* parent); //PAGEBREAK! // Allocate a new inode with the given type on device dev. @@ -220,10 +222,11 @@ fs_iupdate(struct inode *ip) brelse(bp); } + // Find the inode with number inum on device dev // and return the in-memory copy. Does not lock // the inode and does not read it from disk. -static struct inode* +struct inode* iget(uint dev, uint inum, struct inode* parent) { struct inode *ip, *empty; @@ -305,6 +308,7 @@ fs_ipopulate(struct inode* ip) { ip->minor = dip->minor; ip->nlink = dip->nlink; ip->size = dip->size; + ip->mounted = 0; memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); brelse(bp); @@ -476,6 +480,8 @@ fs_readi(struct inode *ip, char *dst, uint off, uint n) return n; } + + // PAGEBREAK! // Write data to inode. int @@ -540,6 +546,9 @@ dirlookup(struct inode *dp, char *name, uint *poff) if(poff) *poff = off; inum = de.inum; + + if(dp->mounted) return iget(dp->mounted, inum, dp); + return iget(dp->dev, inum, dp); } } @@ -647,6 +656,7 @@ namex(char *path, int nameiparent, char *name) return 0; } iunlockput(ip); + ip = next; } if(nameiparent){ diff --git a/proc.c b/proc.c index a642f5a..a038265 100644 --- a/proc.c +++ b/proc.c @@ -18,6 +18,8 @@ int nextpid = 1; extern void forkret(void); extern void trapret(void); +extern void init_procfs(void); + static void wakeup1(void *chan); void @@ -340,6 +342,7 @@ forkret(void) // be run from main(). first = 0; initlog(); + init_procfs(); } // Return to "caller", actually trapret (see allocproc). diff --git a/procfs.c b/procfs.c new file mode 100644 index 0000000..f24eb94 --- /dev/null +++ b/procfs.c @@ -0,0 +1,217 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "stat.h" +#include "mmu.h" +#include "proc.h" +#include "spinlock.h" +#include "buf.h" +#include "fs.h" +#include "file.h" + +#define PROCFS_DEV 9 +#define PROCDIR_OFF 1000 +#define IMEMINFO 1 +#define ICPUINFO 2 + +extern +struct { + struct spinlock lock; + struct proc proc[NPROC]; +} ptable; + +extern +struct inode* iget(uint dev, uint inum, struct inode* parent); + +struct inode_functions procfs_i_func = { procfs_ipopulate, procfs_iupdate, procfs_readi, procfs_writei }; + +void init_procfs(){ + struct inode *ip = namei("/proc"); + ip->i_func = &procfs_i_func; +} + +void procfs_iupdate(struct inode *ip) +{ + +} + +void +procfs_ipopulate(struct inode* ip){ + ip->major = 0; + ip->minor = 0; + ip->nlink = 1; + ip->flags |= I_VALID; + ip->mounted = PROCFS_DEV; + ip->size = 0; + + //Only real directory /proc + if(ip->dev != PROCFS_DEV){ + ip->type = T_DIR; + + iget(PROCFS_DEV, IMEMINFO, ip); + iget(PROCFS_DEV, ICPUINFO, ip); + + ip->size = 2*sizeof(struct dirent); + + struct proc *p; + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->state != UNUSED){ + iget(PROCFS_DEV,p->pid+PROCDIR_OFF,ip); + ip->size += sizeof(struct dirent); + } + } + + return; + } + + //Virtual Proccess Directory + if(ip->inum > PROCDIR_OFF && ip->inum < (2*PROCDIR_OFF)){ + ip->type = T_DIR; + ip->size = 2*sizeof(struct dirent); + + return; + } + + //Virtual File + ip->type = T_FILE; +} + + + +void toString(int x, char *buf, int max){ + if(x < 0 && max < 1) return; + + int i = 0; + do{ + buf[i++] = '0' + (x % 10); + } while((x /= 10) != 0 && i < max); + + buf[i] = '\0'; +} +int +procfs_readi(struct inode *ip, char *dst, uint off, uint n) +{ + if(ip->dev != PROCFS_DEV){ + if(ip->type != T_DIR) return -1; + + struct dirent de; + int c = off / sizeof(de); + + if(c-- == 0){ + de.inum = IMEMINFO; + memmove(de.name,"meminfo",DIRSIZ); + } + else if(c-- == 0){ + de.inum = ICPUINFO; + memmove(de.name,"cpuinfo",DIRSIZ); + } + else{ + char buf[DIRSIZ]; + struct proc *p; + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state != UNUSED && c-- == 0){ + toString(p->pid, buf, DIRSIZ); + de.inum = p->pid + PROCDIR_OFF; + memmove(de.name,buf,DIRSIZ); + break; + } + + if(c >= 0) return -1; + } + memmove(dst,&de,sizeof(de)); + + return n; + } + + + if(ip->inum > PROCDIR_OFF && ip->inum < 2*PROCDIR_OFF){ + if(ip->type != T_DIR) return -1; + + struct dirent de; + int c = off / sizeof(de); + + if(c > 1) return -1; + + int inum = ip->inum - PROCDIR_OFF; + inum = 10*inum + 2*PROCDIR_OFF; + + if(c==0){ + iget(PROCFS_DEV,inum,ip); + de.inum = inum; + memmove(de.name,"name",DIRSIZ); + } + else{ + iget(PROCFS_DEV,inum+1,ip); + de.inum = inum+1; + memmove(de.name,"parent",DIRSIZ); + } + + memmove(dst,&de,sizeof(de)); + } + + + if(ip->inum < PROCDIR_OFF){ + if(ip->type != T_FILE) return -1; + + switch(ip->inum){ + case IMEMINFO: + case ICPUINFO: + default: cprintf("huh?\n"); return -1; break; + } + } + + + if(ip->inum > 2*PROCDIR_OFF){ + if(ip->type != T_FILE) return -1; + + if(off > 16 ) return -1; + + if(off + n > 16) n = 16 - off; + + int pid = (ip->inum - 2*PROCDIR_OFF) / 10; + int info = (ip->inum - 2*PROCDIR_OFF) % 10; + + char buf[16]; + struct proc *p; + int slen; + switch(info){ + case 0: + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state != UNUSED && p->pid == pid){ + slen = strlen(p->name); + memmove(buf,p->name,slen); + break; + } + + buf[slen+1] = '\n'; + buf[slen+2] = '\0'; + + memmove(dst,buf+off,n); + break; + + case 1: + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state != UNUSED && p->pid == pid){ + slen = strlen(p->name); + memmove(buf,p->parent->name,slen); + break; + } + + buf[slen+1] = '\n'; + buf[slen+2] = '\0'; + + memmove(dst,buf+off,n); + break; + default: + cprintf("huh?\n"); + return -1; + break; + } + } + + return n; +} + +int procfs_writei(struct inode *ip, char *src, uint off, uint n){ + return 0; +}