Unix API
- general I/O
- different from C standard library (fopen, fprintf, ...)
- basic operations are:
- int read(int f, char * b, int size)
- int write(int f, char * b, int ct)
- additional operations include:
- open
- close
- flush
- seek
- ioctl
Unix File Descriptors
- handles for I/O
- small integers:
\setcounter{enumi}{-1}
- standard input
- standard output
- standard error
- indices into an array containing information for each open descriptor
- created by:
- int open(char * path, int f, int m) or
int creat(char * path, int flags) for files
- int pipe(int fd [2]) for pipes
- int socket(int domain, int type,
int protocol)
for sockets
Unix Files
- each file identified by an integer (inode)
- inode table tells for each inode where the corresponding disk
blocks are
- contents, ownership, permissions are associated with the inode
- directories are regular files (with a different bit in the permissions)
- directories store the name of the file and the inode number
- hard links are two different paths (names) for the same inode
- each directory has a hard link to itself (".") and its
parent ("..")
- a soft link is a name pointing to another name
Unix File Systems
- each unix system has at least one file system, the root,
written "/"
- a system may have multiple file systems
- every file system but root has a mount point, which is the
name of a directory:
- when the file system is unmounted, the contents of the directory
are accessible
- when the file system is mounted, the contents of the file system
are accessible
- /etc/fstab has a list of file systems
- a file can only be on one file system:
- mv within a file system does not require copying
- mv between file systems requires copying
Buffering
- for most kinds of I/O, reading or writing many bytes at a time is
more efficient than one character at a time
- some devices (e.g. disks, networks) even require us to read
a block at a time
- but the application may only want one character at a time
- reading: read a whole block, even if the user asks for a single character
- when the next character is read, read it from memory instead of device
- writing: accumulate characters in memory, only write them when we
have "enough"
Buffering: problems
- if we want to read a block of b characters, and the device only
has n < b characters ready, we can either:
- give n characters, and be less efficient
- wait for b characters, and block the application
- when line buffering, no guarantee about maximum line
length, so hard to get right
- if we wait for b characters before writing to disk or a pipe:
- if the program crashes, the characters can be lost
- if we have circular dependencies (pipes, files), may deadlock with
buffering even though without buffering it would not
Buffering: Unix
- stdin (fd = 0) is generally line buffered (can be
changed with stty, tcsetattr, or ioctl)
- stdout (fd = 1) is generally line buffered (can
be flushed)
- stderr (fd = 2) is unbuffered