The interface between user processes and the kernel implementation of the VFS is formed, as usual, by system calls, most of which involve the manipulation of files, directories, and filesystems in general. At this point, we will not concern ourselves with the specific details of system programming as these are the subject of many other publications such as [SR05] and [Her03].
The kernel provides more than 50 system calls for the above manipulations. We look only at the most important calls to demonstrate the key principles.2
Files must be opened with the open or openat system call before they can be used. The kernel returns a non-negative integer number to userland after opening the file successfully. The assigned file descriptor numbers start at 3. Recall that numbering does not start at 0 because the first three file descriptors are reserved for all processes, although no explicit instructions need be given. 0 represents standard input, 1 standard output, and 2 standard error.
Once a file has been opened, its name has no further significance. It is now uniquely identified by its file descriptor, which is passed as a parameter to all further library functions (and therefore to system calls). While file descriptors were traditionally sufficient to identify a file within the kernel, this is not the case anymore. Since the introduction of multiple namespaces and containers, multiple file descriptors with the same numerical value can coexist in the kernel. A unique representation is provided by a special data structure (struct file), discussed below.
We see this in the close part of the sample program that closes the "connection" to a file (and returns the file descriptor so that it can be used for files to open other files in the future). read also expects the file descriptor as its first parameter so that it can identify the source from which to read data.
The current position within an open file is held in the file pointer, which is an integer that specifies the offset from the start of the file. The pointer can be set to any value for random access files as long as the value remains within the file limits. This supports random access to the file data. Other file types — named pipes or device files for character devices, for instance — prohibit this. They may only be read sequentially from beginning to end.
Various flags (such as o_rdonly) are specified to define the access mode when a file is opened. More detailed explanations are given in all works on system programming.
Continue reading here: Files as a Universal Interface
Was this article helpful?