Jerry's blog

Linux File

Almost everything in Posix is handled through a file descriptor

File descriptors: These are small integers that you can use to access open files or devices.

Programs can use disk files, serial ports, printers and other devices in exactly the same way as they would use a file: open, close, read, write and ioctl.

file descriptor

Each Unix process (except perhaps a daemon) should expect to have three standard POSIX file descriptors, corresponding to the three standard streams. The file descriptors that are automatically opened, however, already allow us to create some simple programs using write.

Integer value feilds
0 standard input
1 standard output
2 standard error

write

#include <unistd.h>
size_t write(int fildes, const void *buf, size_t nbytes);

read

#include <unistd.h>
size_t read(int fildes, void *buf, size_t nbytes);

open

To create a new file descriptor we need to use the open system call.

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int open(const char *path, int oflags);
int open(const char *path, int oflags, mode_t mode);

Note Strictly speaking, we don’t need to include sys/types.h and sys/stat.h to use open on POSIX systems, but they may be necessary on some UNIX systems.

If two programs have a file open at the same time, they maintain distinct file descriptors. If they both write to the file, they will continue to write where they left off. Their data isn’t interleaved, but one will overwrite the other. Each keeps its own idea of how far into the file (the offset) it has read or written.

The name of the file or device to be opened is passed as a parameter, path, and the oflags parameter is used to specify actions to be taken on opening the file.

The oflags are specified as a bitwise OR of a mandatory file access mode and other optional modes. The open call must specify one of the following file access modes:

kernal use three different types of data structure to represent opened files

Mode Description
O_RDONLY Open for read−only
O_WRONLY Open for write−only
O_RDWR Open for reading and writing

The call may also include a combination (bitwise OR) of the following optional modes in the oflags parameter:

Mode Description
O_APPEND Place written data at the end of the file.
O_TRUNC Set the length of the file to zero, discarding existing contents.
O_CREAT Creates the file, if necessary, with permissions given in mode.
O_EXCL Used with O_CREAT, ensures that the caller creates the file. The open is atomic, i.e. it’s performed with just one function call. This protects against two programs creating the file at the same time. If the file already exists, open will fail.

open returns the new file descriptor (always a non−negative integer) if successful, or −1 if it fails, when open also sets the global variable errno to indicate the reason for the failure. The new file descriptor is always the lowest numbered unused descriptor, a feature that can be quite useful in some circumstances.

Initial Permissions

When we create a file using the O_CREAT flag with open, we must use the three parameter form. mode, the third parameter, is made from a bitwise OR of the flags defined in the header file sys/stat.h.

Mode Permission
S_IRUSR Read permission, owner.
S_IWUSR Write permission, owner.
S_IXUSR Execute permission, owner.
S_IRGRP Read permission, group.
S_IWGRP Write permission, group.
S_IXGRP Execute permission, group.
S_IROTH Read permission, others.
S_IWOTH Write permission, others.
S_IXOTH Execute permission, others.
open ("myfile", O_CREAT, S_IRUSR|S_IXOTH);

string must be “”, char ‘’

close

#include <unistd.h>
int close(int fildes);

It returns 0 if successful and −1 on error.

standard IO

With that said, some things in Posix, and in particular, in Linux, are definitely not files.

The most obvious ones are signals. They are handled asynchronously to the program’s execution, and therefor cannot take on a file interface. For that purpose, pselect and one of its better alternatives were invented.

Things more subtly not files are thread synchronization constructs (mutexs, semaphores, etc.). Some attempt have been made to make those available as file descriptors as well (see signalfd and eventfd), but those hardly caught on. I believe that this is due, in large part, for them having a vastly different performance profiles than the ususal way of handling them.