File handling is at the core of any Unix system, and the
fs
directory in Linux is the fattest of all
directories. It includes all the filesystems supported by the current
Linux version, each in its own subdirectory, as well as the most
important system calls after fork and
exit.
The execve system call lives in
exec.c
and relies on the various available binary
formats to actually interpret the binary data found in the executable
files. The most important binary format nowadays is ELF, implemented
by
binfmt_elf.c
. binfmt_script.c
supports the execution of interpreted files. After detecting the need
for an interpreter (usually on the #!
or “shebang”
line), the file relies on the other binary formats to load the
interpreter.
Miscellaneous binary formats (such as the Java executable format) can
be defined by the user with a /proc
interface
defined in binfmt_misc.c
. The
misc binary format is able to identify an
interpreted binary format based on the contents of the executable
file, and fire the appropriate interpreter with appropriate
arguments. The tool is configured via
/proc/sys/fs/binfmt_misc
.
The fundamental system calls for file access are defined in
open.c
and read_write.c
. The
former also defines close and several other
file-access system calls (chown, for instance).
select.c
implements select
and poll. pipe.c
and
fifo.c
implement pipes and named pipes.
readdir.c
implements the
getdents system call, which is how user-space
programs read directories (the name stands for “get directory
entries”). Other programming interfaces to access directory data
(such as the readdir interface) are all
implemented in user space as library functions, based on the
getdents system call.
Most system calls related to moving files around, such as
mkdir, rmdir,
rename, link,
symlink, and mknod, are
implemented in namei.c
, which in turn lays its
foundations on the directory entry cache that lives in
dcache.c
.
Mounting and unmounting filesystems, as well as support for the use of
a temporary root for initrd, are implemented in
super.c
.
Of particular interest to device driver writers is
devices.c
, which implements the char and block
driver registries and acts as dispatcher for all devices. It does so
by implementing the generic open method that is
used before the device-specific file_operations
structure is fetched and used. read and
write for block devices are implemented in
block_dev.c
, which in turn delegates to
buffer.c
everything related to buffer management.
There are several other files in this directory, but they are less
interesting. The most important ones are inode.c
and file.c
, which manage the internal
organization of file and inode data structures;
ioctl.c
, which implements
ioctl; and dquot.c
, which
implements quotas.
As we suggested, most of the subdirectories of fs
host individual filesystem implementations. However,
fs/partitions
is not a filesystem type but rather
a container for partition management code. Some files in there are
always compiled, regardless of kernel configuration, while other files
that implement support for specific partitioning schemes can be
individually enabled or disabled.