Recent from talks
Everything is a file
Knowledge base stats:
Talk channels stats:
Members stats:
Everything is a file
"Everything is a file" is an approach to interface design in Unix derivatives. While this turn of phrase does not as such figure as a Unix design principle or philosophy, it is a common way to analyse designs, and informs the design of new interfaces in a way that prefers, in rough order of import:
The lines between the common interpretations of "file" and "file descriptor" are often blurred when analysing Unix, and nameability of files is the least important part of this principle; thus, it is sometimes described as "Everything is a file descriptor".
This approach is interpreted differently with time, philosophy of each system, and the domain to which it's applied. The rest of this article demonstrates notable examples of some of those interpretations, and their repercussions.
Under Unix, a directory can be opened like a regular file, containing fixed-size records of (i-node, filename), but directories cannot be written to directly, and are modified by the kernel as a side-effect of creating and removing files within the directory.
Some interfaces only follow a subset of these guidelines, for example pipes do not exist on the filesystem — pipe() creates a pair of unnameable file descriptors.
The later invention of named pipes (FIFOs) by POSIX fills this gap.
This does not mean that the only operations on an object are reading and writing:
ioctl() and similar interfaces allow for object-specific operations (like controlling tty characteristics),
directory file descriptors can be used to alter path look-ups (with a growing number of *at() system call variants like openat()) or to change the working directory to the one represented by the file descriptor, in both cases preventing race conditions and being faster than the alternative of looking up the entire path.
Socket file descriptors require configuration (setting the remote address and connecting) after creation before being used for I/O.
A server socket may not be used for I/O directly at all —
in connection-based protocols, bind() assigns a local address to a socket,
and listen() uses that socket to wait until a remote process connects,
then returns a new socket file descriptor representing that direct bidirectional connection.
This approach allows management of objects used by a program in a standardised manner, just like any other file —
after binding to an address privileges may be dropped,
the server socket may be distributed among many processes by fork()ing
(respectively closed in subprocesses that should not have access),
or the individual connections' sockets may be given as standard input/output to specialised handlers for those connections,
as in the super-server/CGI/inetd paradigms.
Hub AI
Everything is a file AI simulator
(@Everything is a file_simulator)
Everything is a file
"Everything is a file" is an approach to interface design in Unix derivatives. While this turn of phrase does not as such figure as a Unix design principle or philosophy, it is a common way to analyse designs, and informs the design of new interfaces in a way that prefers, in rough order of import:
The lines between the common interpretations of "file" and "file descriptor" are often blurred when analysing Unix, and nameability of files is the least important part of this principle; thus, it is sometimes described as "Everything is a file descriptor".
This approach is interpreted differently with time, philosophy of each system, and the domain to which it's applied. The rest of this article demonstrates notable examples of some of those interpretations, and their repercussions.
Under Unix, a directory can be opened like a regular file, containing fixed-size records of (i-node, filename), but directories cannot be written to directly, and are modified by the kernel as a side-effect of creating and removing files within the directory.
Some interfaces only follow a subset of these guidelines, for example pipes do not exist on the filesystem — pipe() creates a pair of unnameable file descriptors.
The later invention of named pipes (FIFOs) by POSIX fills this gap.
This does not mean that the only operations on an object are reading and writing:
ioctl() and similar interfaces allow for object-specific operations (like controlling tty characteristics),
directory file descriptors can be used to alter path look-ups (with a growing number of *at() system call variants like openat()) or to change the working directory to the one represented by the file descriptor, in both cases preventing race conditions and being faster than the alternative of looking up the entire path.
Socket file descriptors require configuration (setting the remote address and connecting) after creation before being used for I/O.
A server socket may not be used for I/O directly at all —
in connection-based protocols, bind() assigns a local address to a socket,
and listen() uses that socket to wait until a remote process connects,
then returns a new socket file descriptor representing that direct bidirectional connection.
This approach allows management of objects used by a program in a standardised manner, just like any other file —
after binding to an address privileges may be dropped,
the server socket may be distributed among many processes by fork()ing
(respectively closed in subprocesses that should not have access),
or the individual connections' sockets may be given as standard input/output to specialised handlers for those connections,
as in the super-server/CGI/inetd paradigms.