File I/O - the universal I/O model
Universality of I/O
- One of the distinguishing features of the I/O model on UNIX systems is the concept of universality of I/O.
This means that the same system calls (
open(),read(),write(),close(), and so on) are used to perform I/O on all types of files, including devices. Thus, a program that employing these systems will work on any type of file.
$ ./copy test test.old # Copy a regular file$ ./copy a.txt /dev/tty # Copy a regular file to this terminal$ ./copy /dev/tty b.txt # Copy input from this terminal to a regular file$ ./copy /dev/pts/16 /dev/tty # Copy input from another terminal- All system calls for performing I/O refer to open files using a
file descriptor(a nonnegative integer). File descriptors are used to refer to all types of open files: pipes, FIFOs, sockets, terminals, devices and regular files. Each process has its own set of file descriptors.
Opening a file: open()
- A call to open() creates a new open file description, an entry in
the system-wide table of open files. The open file description
records the file offset and the file status flags (see below). A file descriptor is a non-negative integer that act as an abstract to handle file or I/O resources
0,1,2 are taken by
STDIN,STDOUT, andSTDERR.
#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags, ... /* mode_t mode */);
// Returns file descriptor on success, or –1 on errorExplain
-
The file to be opened is identified by the
pathnameargument. Ifpathnameis asymboliclink, it is dereferenced. -
The
flagsargument is a bitmask that specifies theaccess modefor the file:Access mode Description Group O_RDONLYOpen for reading only File access mode flags O_WRONLYOpen for writing only File access mode flags O_RDWROpen for reading and writing File access mode flags O_CLOEXECSet the close-on-exec flag (since Linux 2.6.23) File creation flags O_CREATCreate file if it doesn’t already exist File creation flags O_DIRECTFile I/O bypasses buffer cache File creation flags O_DIRECTORYFail if pathnameis not a directoryFile creation flags O_EXCLWith O_CREAT: create file exclusivelyFile creation flags O_LARGEFILEUsed on 32-bit systems to open large files File creation flags O_NOATIMEDon’t update file last access time on read()(since Linux 2.6.8)File creation flags O_NOCTTYDon’t let pathnamebecome the controlling terminalFile creation flags O_NOFOLLOWDon’t dereference symbolic links File creation flags O_TRUNCTruncate existing file to zero length File creation flags O_APPENDWrites are always appended to end of file Open file status flags O_ASYNCGenerate a signal when I/O is possible Open file status flags O_DSYNCProvide synchronized I/O data integerity (since Linux 2.6.33) Open file status flags O_NONBLOCKOpen in nonblocking mode Open file status flags O_SYNCMake file write synchronous Open file status flags File access mode flags: can be retrieved using thefcntl() F_GETFLoperationFile creation mode flags: these flags control various aspects of the behavior of theopen()call and options for subsequent I/O operations. They can’t be retrieved or changed.Open file status flags: these flags can be retrieved and modified using thefcntl()F_GETFLandF_SETFLoperations
Errors handling
-
If an error occurs while trying to open the file,
open()returns –1, anderrnoidentifies the cause of the errorNAME Description EACCES The file permissions don’t allow the calling process to open the file in the mode specified by flags. Alternatively, because of directory permissions, the file could not be accessed, or the file did not exist and could not be created. EISDIR The specified file is a directory, and the caller attempted to open it for writing. This isn’t allowed. EMFILE The process resource limit on the number of open file descriptors has been reached ENFILE The system-wide limit on the number of open files has been reached. ENOENT The specified file doesn’t exist, and O_CREAT was not specified, or O_CREAT was specified, and one of the directories in pathname doesn’t exist or is a symbolic link pointing to a nonexistent pathname (a dangling link). EROFS The specified file is on a read-only file system and the caller tried to open it for writing. ETXTBSY The specified file is an executable file (a program) that is currently executing. It is not permitted to modify (i.e., open for writing) the executable file associated with a running program. (We must first terminate the program in order to be able to modify the executable file.)
Example
Reading from a file: read()
#include <tlpi_hdr.h>
#define MAX_READ 20int main(){ char buffer[MAX_READ + 1]; ssize_t numRead = read(STDIN_FILENO, buffer, MAX_READ); if (numRead == -1) errExit("read"); printf("The input data was: %s\n", buffer);
buffer[numRead] = '\0'; printf("The input data was: %s\n", buffer);}- This system call doesn’t place a terminating null byte at the end of the string.