- Forward


UNIX Input/Output
Working with Disk Files and the File System


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu

Print

Review
Back SMYC Forward
  • Files in UNIX:
    • A file is a sequence of bytes
    • All I/O devices are modeled as files
    • A device driver is the code that allows for (the standard set of) operations to be performed on an I/O device
  • File Descriptors:
    • A (usually small) nonnegative integer that an application can use to identify a file
  • Universal Operations:
    • All files have some common functionality (e.g., open, read, write, close)
Some Common (though Not Universal) Operations
Back SMYC Forward
  • Change the Current File Position:
    • Request a change to the file position (that is an offset from the first byte) maintained by the kernel
  • Control:
    • Manipulate the underlying device parameters
Changing the File Offset: lseek() lseek
Back SMYC Forward
off_t lseek(int fd, off_t offset, int whence);
Purpose:
Reposition the (logical) file offset of an open file descriptor (without causing any physical device access)
Details:
fd The file descriptor
offset The offset (in bytes)
whence The base point from which offset is to be interpreted
Return The new file offset; -1 on error
#include <unistd.h> unistd.h
Changing the File Offset: whence Values
Back SMYC Forward

SEEK_SET The base is the beginning of the file (i.e., the file offset is set to offsetn which must be non-negative)
SEEK_CUR The base is the current offset
SEEK_END The base is the size of the file

Some Common Idioms
Back SMYC Forward
// Obtain the current file offset current = lseek(fd, 0, SEEK_CUR); // Set the file offset to the start of the file lseek(fd, 0, SEEK_SET); // Set the file offset to the next byte after the end of the file lseek(fd, 0, SEEK_END);
A Common Sequence of Calls
Back SMYC Forward
// Save the current file offset original = lseek(fd, 0, SEEK_CUR); // Set the file offset to a particular value lseek(fd, offset, SEEK_SET); // Read from the new file offset size = read(fd, buffer, length); // Reset the file offset lseek(fd, original, SEEK_SET);

Unfortunately, this sequence of calls is not atmoic (i.e., might be interrupted)!

Reading from an Offset: pread() pread
Back SMYC Forward
ssize_t pread(int fd, void* buffer, size_t count, off_t offset);
Purpose:
Atomically read from a specific file offset, without changing the offset
Details:
fd The file descriptor to read from
buffer The ultimate location of the bytes in memory
count The maximum number of bytes to copy
offset The file offset to copy from
Return The number of bytes copied; 0 on EOF; -1 on error
#include <unistd.h> unistd.h
Writing to an Offset: pwrite() pwrite
Back SMYC Forward
ssize_t pwrite(int fd, const void *buffer, size_t count, off_t offset
Purpose:
Atomically write to a specific file offset, without changing the offset
Details:
fd The file descriptor to copy to
buffer The memory to copy from
count The maximum number of bytes to copy
offset The file offset to copy to
Return The number of bytes copied; -1 on error
#include <unistd.h> unistd.h
There's Always More to Learn
Back -