FD_DEVICE

This commit is contained in:
Robert Morris 2019-06-13 10:29:27 -04:00
parent 46744c4a13
commit a8305b7318
7 changed files with 42 additions and 43 deletions

View file

@ -156,20 +156,18 @@ struct {
#define C(x) ((x)-'@') // Contro #define C(x) ((x)-'@') // Contro
int int
consoleread(struct inode *ip, int user_dst, uint64 dst, int n) consoleread(int user_dst, uint64 dst, int n)
{ {
uint target; uint target;
int c; int c;
char buf[1]; char buf[1];
iunlock(ip);
target = n; target = n;
acquire(&cons.lock); acquire(&cons.lock);
while(n > 0){ while(n > 0){
while(input.r == input.w){ while(input.r == input.w){
if(myproc()->killed){ if(myproc()->killed){
release(&cons.lock); release(&cons.lock);
ilock(ip);
return -1; return -1;
} }
sleep(&input.r, &cons.lock); sleep(&input.r, &cons.lock);
@ -192,17 +190,15 @@ consoleread(struct inode *ip, int user_dst, uint64 dst, int n)
break; break;
} }
release(&cons.lock); release(&cons.lock);
ilock(ip);
return target - n; return target - n;
} }
int int
consolewrite(struct inode *ip, int user_src, uint64 src, int n) consolewrite(int user_src, uint64 src, int n)
{ {
int i; int i;
iunlock(ip);
acquire(&cons.lock); acquire(&cons.lock);
for(i = 0; i < n; i++){ for(i = 0; i < n; i++){
char c; char c;
@ -211,7 +207,6 @@ consolewrite(struct inode *ip, int user_src, uint64 src, int n)
consputc(c); consputc(c);
} }
release(&cons.lock); release(&cons.lock);
ilock(ip);
return n; return n;
} }

View file

@ -73,9 +73,9 @@ fileclose(struct file *f)
f->type = FD_NONE; f->type = FD_NONE;
release(&ftable.lock); release(&ftable.lock);
if(ff.type == FD_PIPE) if(ff.type == FD_PIPE){
pipeclose(ff.pipe, ff.writable); pipeclose(ff.pipe, ff.writable);
else if(ff.type == FD_INODE){ } else if(ff.type == FD_INODE || ff.type == FD_DEVICE){
begin_op(); begin_op();
iput(ff.ip); iput(ff.ip);
end_op(); end_op();
@ -90,7 +90,7 @@ filestat(struct file *f, uint64 addr)
struct proc *p = myproc(); struct proc *p = myproc();
struct stat st; struct stat st;
if(f->type == FD_INODE){ if(f->type == FD_INODE || f->type == FD_DEVICE){
ilock(f->ip); ilock(f->ip);
stati(f->ip, &st); stati(f->ip, &st);
iunlock(f->ip); iunlock(f->ip);
@ -113,6 +113,8 @@ fileread(struct file *f, uint64 addr, int n)
if(f->type == FD_PIPE){ if(f->type == FD_PIPE){
r = piperead(f->pipe, addr, n); r = piperead(f->pipe, addr, n);
} else if(f->type == FD_DEVICE){
r = devsw[f->major].read(1, addr, n);
} else if(f->type == FD_INODE){ } else if(f->type == FD_INODE){
ilock(f->ip); ilock(f->ip);
if((r = readi(f->ip, 1, addr, f->off, n)) > 0) if((r = readi(f->ip, 1, addr, f->off, n)) > 0)
@ -138,6 +140,8 @@ filewrite(struct file *f, uint64 addr, int n)
if(f->type == FD_PIPE){ if(f->type == FD_PIPE){
ret = pipewrite(f->pipe, addr, n); ret = pipewrite(f->pipe, addr, n);
} else if(f->type == FD_DEVICE){
ret = devsw[f->major].write(1, addr, n);
} else if(f->type == FD_INODE){ } else if(f->type == FD_INODE){
// write a few blocks at a time to avoid exceeding // write a few blocks at a time to avoid exceeding
// the maximum log transaction size, including // the maximum log transaction size, including

View file

@ -1,11 +1,12 @@
struct file { struct file {
enum { FD_NONE, FD_PIPE, FD_INODE } type; enum { FD_NONE, FD_PIPE, FD_INODE, FD_DEVICE } type;
int ref; // reference count int ref; // reference count
char readable; char readable;
char writable; char writable;
struct pipe *pipe; struct pipe *pipe; // FD_PIPE
struct inode *ip; struct inode *ip; // FD_INODE and FD_DEVICE
uint off; uint off; // FD_INODE
short major; // FD_DEVICE
}; };
@ -25,11 +26,10 @@ struct inode {
uint addrs[NDIRECT+1]; uint addrs[NDIRECT+1];
}; };
// table mapping major device number to // map major device number to device functions.
// device functions
struct devsw { struct devsw {
int (*read)(struct inode*, int, uint64, int); int (*read)(int, uint64, int);
int (*write)(struct inode*, int, uint64, int); int (*write)(int, uint64, int);
}; };
extern struct devsw devsw[]; extern struct devsw devsw[];

View file

@ -461,12 +461,6 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n)
uint tot, m; uint tot, m;
struct buf *bp; struct buf *bp;
if(ip->type == T_DEV){
if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].read)
return -1;
return devsw[ip->major].read(ip, user_dst, dst, n);
}
if(off > ip->size || off + n < off) if(off > ip->size || off + n < off)
return -1; return -1;
if(off + n > ip->size) if(off + n > ip->size)
@ -493,13 +487,6 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n)
uint tot, m; uint tot, m;
struct buf *bp; struct buf *bp;
if(ip->type == T_DEV){
if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].write){
return -1;
}
return devsw[ip->major].write(ip, user_src, src, n);
}
if(off > ip->size || off + n < off) if(off > ip->size || off + n < off)
return -1; return -1;
if(off + n > MAXFILE*BSIZE) if(off + n > MAXFILE*BSIZE)

View file

@ -31,8 +31,8 @@ struct superblock {
// On-disk inode structure // On-disk inode structure
struct dinode { struct dinode {
short type; // File type short type; // File type
short major; // Major device number (T_DEV only) short major; // Major device number (T_DEVICE only)
short minor; // Minor device number (T_DEV only) short minor; // Minor device number (T_DEVICE only)
short nlink; // Number of links to inode in file system short nlink; // Number of links to inode in file system
uint size; // Size of file (bytes) uint size; // Size of file (bytes)
uint addrs[NDIRECT+1]; // Data block addresses uint addrs[NDIRECT+1]; // Data block addresses

View file

@ -1,6 +1,6 @@
#define T_DIR 1 // Directory #define T_DIR 1 // Directory
#define T_FILE 2 // File #define T_FILE 2 // File
#define T_DEV 3 // Device #define T_DEVICE 3 // Device
struct stat { struct stat {
short type; // Type of file short type; // Type of file

View file

@ -253,7 +253,7 @@ create(char *path, short type, short major, short minor)
if((ip = dirlookup(dp, name, &off)) != 0){ if((ip = dirlookup(dp, name, &off)) != 0){
iunlockput(dp); iunlockput(dp);
ilock(ip); ilock(ip);
if(type == T_FILE && ip->type == T_FILE) if(type == T_FILE && (ip->type == T_FILE || ip->type == T_DEVICE))
return ip; return ip;
iunlockput(ip); iunlockput(ip);
return 0; return 0;
@ -316,6 +316,12 @@ sys_open(void)
} }
} }
if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){
iunlockput(ip);
end_op();
return -1;
}
if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
if(f) if(f)
fileclose(f); fileclose(f);
@ -323,14 +329,21 @@ sys_open(void)
end_op(); end_op();
return -1; return -1;
} }
if(ip->type == T_DEVICE){
f->type = FD_DEVICE;
f->major = ip->major;
} else {
f->type = FD_INODE;
f->off = 0;
}
f->ip = ip;
f->readable = !(omode & O_WRONLY);
f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
iunlock(ip); iunlock(ip);
end_op(); end_op();
f->type = FD_INODE;
f->ip = ip;
f->off = 0;
f->readable = !(omode & O_WRONLY);
f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
return fd; return fd;
} }
@ -361,7 +374,7 @@ sys_mknod(void)
if((argstr(0, path, MAXPATH)) < 0 || if((argstr(0, path, MAXPATH)) < 0 ||
argint(1, &major) < 0 || argint(1, &major) < 0 ||
argint(2, &minor) < 0 || argint(2, &minor) < 0 ||
(ip = create(path, T_DEV, major, minor)) == 0){ (ip = create(path, T_DEVICE, major, minor)) == 0){
end_op(); end_op();
return -1; return -1;
} }