Lecture 03 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 1 July 29, 2016 File Descriptors • Small, nonnegative number • Each process has own set of file descriptors • Used to refer to all types of open files: • • • • • Regular files Pipes Sockets Terminals Devices 2 July 29, 2016 File Descriptors • Must programs use three file descriptors (FDs): 1. FD 0: standard input (stdin) 2. FD 1: standard output (stdout) 3. FD 2: standard error (stderr) 3 July 29, 2016 File Descriptors • FDs 0, 1, and 2 opened by shell before program starts • Program inherits FDs 0, 1, and 2 from shell program 4 July 29, 2016 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 5 July 29, 2016 Universality of I/O • open(), close(), read(), write() -> I/O on ALL file types • Not just regular files … • … but also sockets, pipes, terminals, etc. • Achieved by ensuring that each file system and device driver implements the same set of I/O system calls 6 July 29, 2016 System Calls for I/O • Four key system calls: fd = open( pathname, flags, mode ); numread = read( fd, buffer, count ); numwritten = write( fd, buffer, count ); status = close( fd ); 7 July 29, 2016 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 8 July 29, 2016 open() int open ( const char *pathname, int flags, mode_t mode ); • • • • • • #include <fcntl.h> Attempts to open file identified by pathname If successful, returns lowest file descriptor On error, returns -1 (and errno set) flags is a bit mask that specifies access mode mode specifies file permissions • Used only if open() creates the file 9 July 29, 2016 open() int open ( const char *pathname, int flags, mode_t mode ); • flags bit masks: (see table 4-3 and page 75+ in book) O_RDONLY – opens file for reading only O_WRONLY – opens file for writing only O_RDWR – opens file for both reading and writing O_CREAT – creates file if it doesn’t exist O_APPEND – write() appended to the file 10 July 29, 2016 open() int open ( const char *pathname, int flags, mode_t mode ); • If error occurs, check errno for cause • Common errno values and causes: • EACCESS – file permissions do not allow access • ENDENT – file doesn’t exist • EROFS – attempted to write to a read-only file • Use perror() to print error messages! 11 July 29, 2016 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 12 July 29, 2016 read() ssize_t read( int fd, void *buffer, size_t count ); • #include <unistd.h> • Attempts to read count bytes into buffer from file fd • Returns (ssize_t is a signed integer): • number of bytes read • 0 on EOF • -1 on error 13 July 29, 2016 read() ssize_t read( int fd, void *buffer, size_t count ); • count specifies maximum number of bytes to read from fd • size_t is an unsigned integer • buffer is memory address where input data will be placed • void * type makes it very flexible (can be anything) • System calls DO NOT allocate memory for buffers • Assumes buffer has already been allocated! 14 July 29, 2016 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 15 July 29, 2016 write() ssize_t write( int fd, void *buffer, size_t count ); • #include <unistd.h> • Attempts to write count bytes from buffer to file fd • Returns (ssize_t is a signed integer): • number of bytes written (may be less than count) • -1 on error 16 July 29, 2016 write() ssize_t write( int fd, void *buffer, size_t count ); • count specifies number of bytes to write to file fd • size_t is an unsigned integer • buffer is memory address of data to be written • void * type makes it very flexible (can be anything) 17 July 29, 2016 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 18 July 29, 2016 close() int close( int fd ); • #include <unistd.h> • Closes an open file descriptor • Returns -1 on failure • Good practice to close files when done using them • File descriptors are a limited resource 19 July 29, 2016 close() int close( int fd ); • Possible reasons why close() might fail: • • • • Trying to close an unopened file descriptor Trying to close a file twice Network File System (NFS) error Function call interrupted by a signal 20 July 29, 2016 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 21 July 29, 2016 lseek() int lseek( int fd, off_t offset, int whence ); • #include <unistd.h> • lseek() changes the file’s offset • Returns -1 on error • Offset – number of bytes relative to file’s beginning 22 July 29, 2016 lseek() int lseek( int fd, off_t offset, int whence ); • fd is the file descriptor to seek • offset specifies offset value in bytes • whence is base pointer from which offset will be interpreted • SEEK_SET – from beginning of file • SEK_CUR – relative to current file offset • SEEK_END – relative to end of file 23 July 29, 2016 lseek() int lseek( int fd, off_t offset, int whence ); • For each open file, kernel keeps track of file offset • Automatically adjusts for read / write operations • Offset points to next byte • Files start with 0 offset 24 July 29, 2016 lseek() • Examples: lseek( fd, 0, SEEK_SET ); //start of file lseek( fd, 0, SEEK_END ); //next byte after EOF lseek( fd, -10, SEEK_CUR ); //10 bytes prior to current offset lseek( fd, 10000, SEEK_END ); 25 July 29, 2016 //10001 bytes past EOF File Holes • Possible to write bytes well past EOF • E.g., lseek( fd, 10000, SEEK_END ); • File hole- space between previous EOF and newly written bytes 26 July 29, 2016 Outline • • • • • • • • File descriptors System calls for universal I/O open() read() write() close() lseek() Live Coding 27 July 29, 2016 Live Coding • Recreate UNIX cp command • UNIX> my_cp source destination • Recreate UNIX tee command • writes stdin to both stdout AND file specified by command line argument • -a command line option for “append” • UNIX> my_tee output • UNIX> my_tee –a output2 28 July 29, 2016