File I/O: Basics¶
File Descriptors¶
Universal handle for everything that’s got to do with I/O
Type:
int
File is only one shape of I/O
Alternative shapes
Pipes
Sockets
FIFOs
Terminals
Device Special Files ⟶ entry point into arbitrary kernel drivers
Linux specific ingenuities:
signalfd()
,timerfd_create()
,eventfd()
Standard Filedescriptors¶
Number |
POSIX Macro |
|
---|---|---|
0 |
|
|
1 |
|
|
2 |
|
|
Interactive shell: all three associated with terminal
Standard input and output used for I/O redirection and pipes
Standard error receives errors, warnings, and debug output
Caution
Windows-Programmers: no errors, warnings, and debug output to standard output!!
File I/O: System Calls¶
|
Opens a file (or creates it ⟶ tons of flags) |
|
Reads bytes |
|
Writes bytes |
|
Closes the file |
open()
creates file descriptors that are associated with path
names (files, named pipes, device special files, …). Other
“factory” functions …
Network programming:
connect()
accept()
Miscellaneous:
pipe()
timerfd_create()
…
open()
¶
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Swiss army knife among system calls. Multiple actions, governed by bitwise-or’ed flags:
Create/Open/Truncate/…
Access mode (Read, Write)
Hundreds of others
open()
Flags¶
Access Mode
O_RDONLY
: Can onlyread()
; error onwrite()
O_WRONLY
: Can onlywrite()
; error onread()
O_RDWR
: …
Creating a File
O_CREAT
: create if not exists, else simply openO_CREAT|O_EXCL
: exclusive creationerror if file exists
⟶ to prevent race conditions when two parties try to create a file at the smae time
security measure
Miscellaneous
O_APPEND
: write access appends at the endO_TRUNC
: truncate file to zero length if already existsO_CLOEXEC
:exec()
closes the file descriptor (⟶ later)
read()
¶
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
Return value: number of bytes read (-1 on error, as always)
0
is End of File (EOF)Can read less than
count
(usually with network I/O)
write()
¶
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
Return value: number of bytes written (-1 on error, as always)
Can write less than
count
(usually with network I/O)SIGPIPE
(process termination) when …Writing on a network connection that has been closed by peer
Writing on a pip where receiver end has exited (hence
SIGPIPE
)
File Offset: lseek()
¶
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
read()
and write()
manipulate the offset (position where the
next operation begins).
Explicit positioning. whence
is one of
Macro |
Description |
---|---|
|
The file offset is set to offset bytes. |
|
The file offset is set to its current location plus offset bytes. |
|
The file offset is set to the size of the file plus offset bytes. |
Obscure feature: files with holes
positioning beyond file size
write to that position
⟶ holes, occupying no space
read()
across a hole give 0-bytes
The Rest: ioctl()
¶
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
Tunnel for functionality not declarable as I/O
Most commonly used to communicate with drivers (e.g.: “Open that CD drive!”)
Mostly deprecated nowadays (though easily implemented in a driver)
Better (because more obvious): use
/proc
and/sys