kernel/file.h
Included by 7 files
kernel/console.c, kernel/file.c, kernel/fs.c, kernel/pipe.c, kernel/printk.c, kernel/sysfile.c, user/init.cAbout this file
The in-memory structures of the file layer: struct file, one open file (struct file);
struct inode, the kernel’s in-memory copy of an inode; and
struct devsw, the table that connects device files to their drivers. Their
on-disk counterparts are in kernel/fs.h.
kernel/file.c and kernel/fs.c contain the code that manages these structures,
and kernel/sysfile.c and kernel/pipe.c use them. The header is also included by
user/init.c, which needs the CONSOLE constant to create the console device file.
Read before: kernel/fs.h. Read next: kernel/fs.c, kernel/file.c.
struct file: one open file
What a file descriptor points to. Each successful open creates one in ftable,
and pipe creates two (one per end); dup and fork make more descriptors point to the same one. The
type decides which of the remaining fields mean anything:
type |
object | fields used |
|---|---|---|
FD_NONE |
(free entry) | none |
FD_PIPE |
one end of a pipe | pipe |
FD_INODE |
a file or directory | ip, off |
FD_DEVICE |
a device such as the console | ip, major |
readable and writable record the access mode chosen at open and are checked on
every fileread and filewrite. They are char only to save space; each holds 0
or 1.
ref is protected by ftable.lock. off is protected by the inode’s lock: code
reads and updates it only while holding ip->lock, which is what keeps processes
that share this struct file from using the same offset twice.
What the entry refers to. FD_NONE (0) is the value of a free entry; an anonymous
enum used directly as the field’s type.
How many file descriptors point to this entry. 0 means the entry is free.
The pipe, for FD_PIPE files.
The inode, for files, directories and devices. The open file holds one inode
reference, dropped by iput in fileclose.
Where the next read or write starts, for FD_INODE files. Devices and pipes have
no offset.
The device’s major number, copied from the inode at open, used to index devsw.
Packing device numbers (unused)
Helpers that pack a major and a minor device number into one value (major in the high
16 bits, minor in the low 16) and unpack them. Nothing in this version of xv6 uses
them: inodes store major and minor as separate fields, and mknod passes them
separately.
They do not interfere with the fields called major and minor in the structures
here: a function-like macro such as major(dev) is expanded only where its name is
followed by (, so f->major is left alone.
Extract the major number (bits 31–16) and the minor number (bits 15–0) from a packed device number.
Pack major m and minor n into one uint.
struct inode: the in-memory copy of an inode
One entry of itable in kernel/fs.c. The fields fall into two groups, protected
by different locks:
dev,inum,ref: which inode this entry holds and how many in-memory pointers refer to it (its reference count). Protected byitable.lock.- everything after
lock: protected bylock, the per-inode sleep lock, exactly as the comment on line 21 says.validrecords whether the fields below it have been read from the disk yet (ilockdoes that). The rest is a copy of the on-disk dinode (on-disk inode), field for field; any change to it must be written back withiupdate.
Note the difference between ref and nlink. ref counts pointers in memory (open
files, current directories, lookups in progress) and is never stored on disk; nlink
is the on-disk link count (nlink), the number of directory entries naming the inode.
Which disk and which inode number this entry holds.
The number of in-memory references; the entry is free when it is 0.
The inode’s sleeplock, taken by ilock. It may be held across disk I/O.
1 once the fields below have been read from the disk.
T_DIR, T_FILE or T_DEVICE (from kernel/stat.h); 0 would mean a free inode.
Device numbers, meaningful only for T_DEVICE inodes.
The link count (nlink): directory entries that name this inode.
The file’s size in bytes.
The disk addresses of the first 12 data blocks, plus the indirect block in
addrs[12].
devsw: from major device number to driver
A device file is an inode of type T_DEVICE whose major number selects a driver.
devsw (defined in kernel/file.c) is indexed by that number; each entry holds two
function pointers. Their arguments are a flag that is 1 if the
address is a user virtual address, the address, and a byte count; they return the
number of bytes transferred or -1. fileread and filewrite call through them
for FD_DEVICE files.
The extern declaration lets every file that includes this header use the array
defined once in file.c.
Pointers to the device’s read and write functions; see the block note for the arguments.
The console's major number
The console is device 1. consoleinit installs its read and write functions in
devsw[CONSOLE], and the first user program, user/init.c, creates the device
file with mknod("console", CONSOLE, 0) if it does not exist, then opens it as file
descriptors 0, 1 and 2.