Skip to content

Commit

Permalink
Begin implementing procfs
Browse files Browse the repository at this point in the history
  • Loading branch information
posobin committed Dec 10, 2015
1 parent b3de0fb commit 0aae954
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 7 deletions.
3 changes: 3 additions & 0 deletions defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ int dirlink(struct inode*, char*, uint);
struct inode* dirlookup(struct inode*, char*, uint*);
struct inode* ialloc(uint, short);
struct inode* idup(struct inode*);
struct inode* iget(uint, uint);
void iinit(void);
void ilock(struct inode*);
void iput(struct inode*);
Expand Down Expand Up @@ -126,6 +127,8 @@ void wakeup(void*);
void yield(void);
struct mm_struct* get_empty_mm(void);
void free_mm(struct mm_struct*);
int procfs_root_read(struct inode*, char*, uint, uint);
int procfs_root_write(struct inode*, char*, uint, uint);

// swtch.S
void swtch(struct context**, struct context*);
Expand Down
5 changes: 5 additions & 0 deletions file.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ struct file {
struct spinlock lock;
};

typedef int (*read_function)(struct inode*, char*, uint, uint);
typedef int (*write_function)(struct inode*, char*, uint, uint);

// in-memory copy of an inode
struct inode {
Expand All @@ -26,6 +28,9 @@ struct inode {
uint gid;
uint mode;

read_function readi;
write_function writei;

// Two files for pipe, used only when type == T_PIPE
struct file *read_file, *write_file;
};
Expand Down
42 changes: 36 additions & 6 deletions fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ iinit(void)
initlock(&icache.lock, "icache");
}

static int
_readi(struct inode *ip, char *dst, uint off, uint n);
static int
_writei(struct inode *ip, char *dst, uint off, uint n);

int
type_to_mode(short type)
{
Expand All @@ -185,7 +190,7 @@ type_to_mode(short type)
return 0;
}

static struct inode* iget(uint dev, uint inum);
struct inode* iget(uint dev, uint inum);

//PAGEBREAK!
// Allocate a new inode with the given type on device dev.
Expand Down Expand Up @@ -236,10 +241,22 @@ iupdate(struct inode *ip)
brelse(bp);
}

void
set_functions(struct inode* ip)
{
if (ip->dev != PROCDEV) {
ip->readi = _readi;
ip->writei = _writei;
} else {
ip->readi = _readi;
ip->writei = _writei;
}
}

// 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 *ip, *empty;
Expand Down Expand Up @@ -269,6 +286,7 @@ iget(uint dev, uint inum)
ip->flags = 0;
ip->read_file = 0;
ip->write_file = 0;
set_functions(ip);
release(&icache.lock);

return ip;
Expand Down Expand Up @@ -456,8 +474,8 @@ stati(struct inode *ip, struct stat *st)

//PAGEBREAK!
// Read data from inode.
int
readi(struct inode *ip, char *dst, uint off, uint n)
static int
_readi(struct inode *ip, char *dst, uint off, uint n)
{
uint tot, m;
struct buf *bp;
Expand All @@ -482,10 +500,16 @@ readi(struct inode *ip, char *dst, uint off, uint n)
return n;
}

int
readi(struct inode *ip, char *dst, uint off, uint n)
{
return ip->readi(ip, dst, off, n);
}

// PAGEBREAK!
// Write data to inode.
int
writei(struct inode *ip, char *src, uint off, uint n)
static int
_writei(struct inode *ip, char *src, uint off, uint n)
{
uint tot, m;
struct buf *bp;
Expand Down Expand Up @@ -516,6 +540,12 @@ writei(struct inode *ip, char *src, uint off, uint n)
return n;
}

int
writei(struct inode *ip, char *dst, uint off, uint n)
{
return ip->writei(ip, dst, off, n);
}

//PAGEBREAK!
// Directories

Expand Down
3 changes: 3 additions & 0 deletions init.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ main(void)
dup(0); // stdout
dup(0); // stderr

mkdir("/proc", 0555);
mount("/proc", "proc");

for(;;){
printf(1, "init: starting login\n");
pid = fork();
Expand Down
1 change: 1 addition & 0 deletions param.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define NINODE 50 // maximum number of active i-nodes
#define NDEV 10 // maximum major device number
#define ROOTDEV 1 // device number of file system root disk
#define PROCDEV 2 // device number of procfs
#define MAXARG 32 // max exec arguments
#define LOGSIZE 10 // max data sectors in on-disk log

66 changes: 66 additions & 0 deletions proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "spinlock.h"
#include "errno.h"
#include "list.h"
#include "fs.h"

struct proc_list {
struct list_head list;
Expand Down Expand Up @@ -650,6 +651,71 @@ kill(int pid)
return -1;
}

static void
itoa(char* dst, int value)
{
if (value < 0) {
*dst = '-';
value = -value;
dst++;
}
char* start = dst;
*dst++ = '0' + value % 10;
value /= 10;
while (value > 0) {
*dst++ = '0' + value % 10;
value /= 10;
}
*dst = '\0';
dst--;
while (dst > start)
{
char temp = *dst;
*dst = *start;
*start = temp;
start++;
dst--;
}
}

int
procfs_root_read(struct inode* ip, char* dst, uint off, uint n)
{
acquire(&ptable.lock);
struct list_head *pos;
uint current_position = 0;
uint written = 0;
uint last = n + off;
list_for_each(pos, &ptable.list) {
struct proc *p = &list_entry(pos, struct proc_list, list)->proc;
if (p->state == UNUSED) continue;
uint previous_position = current_position;
current_position += sizeof(struct dirent);
if (current_position <= off) continue;
if (last <= previous_position) break;
struct dirent entry;
itoa(entry.name, p->pid);
entry.inum = 1;
char* ptr = (char*)&entry;
int size = sizeof(struct dirent);
if (off > previous_position) {
ptr += off - previous_position;
size -= off - previous_position;
}
for (int i = 0; written < n && i < size; ++written, ++i) {
*dst++ = *ptr++;
}
}
release(&ptable.lock);
return written;
}

int
procfs_root_write(struct inode* ip, char* dst, uint off, uint n)
{
return 0;
}

//PAGEBREAK: 36
// Print a process listing to console. For debugging.
// Runs when user types ^P on console.
Expand Down
2 changes: 2 additions & 0 deletions syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ extern int sys_getgroups(void);
extern int sys_clone(void);
extern int sys_exit_group(void);
extern int sys_sched_yield(void);
extern int sys_mount(void);

static int (*syscalls[])(void) = {
[SYS_fork] sys_fork,
Expand Down Expand Up @@ -152,6 +153,7 @@ static int (*syscalls[])(void) = {
[SYS_clone] sys_clone,
[SYS_exit_group] sys_exit_group,
[SYS_sched_yield] sys_sched_yield,
[SYS_mount] sys_mount,
};

void
Expand Down
1 change: 1 addition & 0 deletions syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@
#define SYS_clone 34
#define SYS_exit_group 35
#define SYS_sched_yield 36
#define SYS_mount 37
34 changes: 33 additions & 1 deletion sysfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
#include "stat.h"
#include "err.h"

static struct inode*
create(char *path, short type, short major, short minor, uint mode);

void
fsinit(void)
{
create("/proc", T_DIR, 0, 0, S_IRUGO | S_IXUGO);
}

// Fetch the nth word-sized system call argument as a file descriptor
// and return both the descriptor and the corresponding struct file.
static int
Expand Down Expand Up @@ -336,6 +345,29 @@ create(char *path, short type, short major, short minor, uint mode)
return ip;
}

int
sys_mount(void)
{
char *target, *fstype;
if (argstr(0, &target) < 0 || argstr(1, &fstype) < 0) {
return -EINVAL;
}
if (strncmp(fstype, "proc", 5) != 0) {
return -EINVAL;
}
struct inode* ip;
if (IS_ERR(ip = namei(target))) {
return PTR_ERR(ip);
}
ilock(ip);
ip->readi = procfs_root_read;
ip->writei = procfs_root_write;
iunlock(ip);
// We should not do iput here.
// Otherwise, ip will be flushed out of the memory.
return 0;
}

int
sys_open(void)
{
Expand All @@ -347,7 +379,7 @@ sys_open(void)
if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
return -EINVAL;
ip = 0;
if(omode & O_CREATE && IS_ERR(ip = namei(path))){
if((omode & O_CREATE) && IS_ERR(ip = namei(path))){
if(argint(2, &mode) < 0)
return -EINVAL;
begin_trans();
Expand Down
1 change: 1 addition & 0 deletions user.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ int setgroups(uint, gid_t*);
int getgroups(int, gid_t*);
int exit_group(void) __attribute__((noreturn));
int sched_yield(void);
int mount(char*, char*);

// ulib.c
int stat(char*, struct stat*);
Expand Down
1 change: 1 addition & 0 deletions usys.S
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ SYSCALL(getgroups)
SYSCALL(clone)
SYSCALL(exit_group)
SYSCALL(sched_yield)
SYSCALL(mount)

0 comments on commit 0aae954

Please sign in to comment.