What UNIX means by "file"
◈ 8 cardsThe byte-sequence definition, why device independence follows from it rather than being bolted on, and the seven file types with the type character that identifies each.
A file is a sequence of bytes
UNIX defines a file in one sentence, and the sentence is deliberately empty: a file is a sequence of bytes. The kernel imposes no records, no fields, no line structure and no type. It will not tell you that one file is a C program and another is a compressed archive, because to the kernel they are the same kind of object and differ only in who opens them. All meaning is supplied by the program reading the bytes.
That emptiness is the design, not a shortcoming, and its first consequence is the slogan everything is a file. Disks, keyboards, terminals, printers, network interfaces, directories, pipes and sockets all live in the same namespace and are reached with the same four operations — open, read, write, close — that you use on an ordinary file.
Device independence in UNIX I/O is therefore not a separate feature somebody added later; it falls out of the model. A program that copies bytes from its input to its output works unchanged whether that input is a file on disk, a terminal, a tape drive or a pipe from another program. Nobody had to write those cases separately, and a device that did not exist when the program was compiled works with it anyway. This is the answer the exam wants when it asks why UNIX I/O is device independent: not "because there are drivers", but because a device is presented as a file, so the file interface is the device interface.
The qualifier matters as much as the slogan. Users and processes are the things that are not files. They are the two active parties in the system — the one that owns things and the one that does things — and they are represented by kernel structures, not by entries in the file system.
Seven types, one character
Every object in the file system is one of seven types, and the first character of an ls -l line names which. Learn to read that character before you read anything else on the line, because it decides what the rest of the line means: a size of 8 on an ordinary file is eight bytes of data, while a size of 8 on a symbolic link is an eight-character pathname.
Worked example — six objects, six answers
Ask for a long listing of three deliberately different things. -d is doing real work here: without it, ls -l /tmp would list what is inside /tmp instead of describing /tmp itself.
$ ls -ld / /tmp /etc/passwd
drwxr-xr-x 19 root root 4096 Aug 12 08:31 /
drwxrwxrwt 14 root root 12288 Sep 1 11:02 /tmp
-rw-r--r-- 1 root root 2914 Jul 3 14:20 /etc/passwd
First characters: d, d, -. Two directories and one ordinary file. A directory is not a special kind of container the kernel hides from you — it is a file whose bytes are a table of (inode number, name) pairs, and the only reason you cannot cat it usefully is that the bytes are structured for the kernel rather than for you.
Now ask about some devices:
$ ls -l /dev/null /dev/loop0
crw-rw-rw- 1 root root 1, 3 Sep 1 08:44 /dev/null
brw-rw---- 1 root disk 7, 0 Sep 1 08:44 /dev/loop0
c and b. Both are special files: they hold no data at all, and where an ordinary listing prints a size these print two numbers — a major number naming the driver and a minor number naming which device that driver should talk to. c is character-oriented (a terminal, a keyboard: bytes arrive one at a time), b is block-oriented (a disk: the kernel transfers a fixed-size block at a time through a cache).
The remaining three types are l for a symbolic link, p for a named pipe or FIFO, and s for a socket. A named pipe is an IPC channel with a name in the file system, so two unrelated processes on the same machine can find it; a socket is the endpoint for IPC that may cross machines. Both are files by the same definition — a sequence of bytes you open, read and write — which is exactly the point.
Extensions are a human convention
A filename is a string, and the kernel attaches no meaning to any part of it. report.jpg may hold a shell script; a.out may hold a photograph. Some programs insist on an extension (a C compiler wants .c so it knows which front end to run), and humans benefit from the convention, but nothing in the file system enforces it. The command that answers "what is actually in this file?" is file, which reads the leading bytes and classifies them by content.