Using Files
Systems Programming
COP-3402
Table of Contents
What is systems software?
The bridge between kernel and applications
Applications |
Systems software |
Kernel |
Hardware |
Kernel design
Kernel virtualizes hardware
- Abstract away hardware difference
- Share hardware resources
- Protect hardware from users
Kernel-/user-space boundary
(Diagram)
- User-space application opens a file
- Kernel-space function implement file abstraction
- Hardware stores file contents
Kernel provides library of functions to manage kernel abstractions.
User applications call kernel to interface to hardware and maintain abstractions on its behalf.
For example, calling open is a kernel library function which handles paths, the file abstraction, and interfacing with storage hardware
This is the case for so-called monolithic kernels, where kernel abstractions are largely managed in kernel space.
https://en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
Kernel interface: syscalls
- System calls (syscalls)
- Functions that operate on kernel abstractions
- Processes, memory, files, etc.
Implementation: protected mode
- LPI Figure 3-1
- Hardware interrupt to enter kernel space
How do we enforce kernel protections?
Learn more about kernel design in operating systems.
System Calls (syscalls)
Making syscalls
- Just like a C function
- The C library handles
- Setting up parameters
- Triggering interrupt
- Collecting return values and error states
You can add your own syscall to Linux!
What syscalls are available?
man syscalls
manpage sections
man man
- Section 2: system calls
- Section 3: library calls
C library calls
man 3 fopen man 3 fprintf man 3 fscanf
Operates on FILE data structures, a C library abstraction. Adds additional features, like buffering, formatting, etc.
Diagram showing the difference w.r.t. to the kernel boundary.
syscalls
man 2 open man 2 write man 2 read
Operates directly on kernel files, references by file descriptors. Work with raw bytes.
Error handling
The UNIX way
- DIY error handling
- Check syscall return value
- Inspect error state
Example: open()
int fd = open(path, O_RDONLY); if (-1 == fd) { fprintf(stderr, "open failed with error %d\n", errno); exit(EXIT_FAILURE); }
Check return value for error.
Look at errno for type of error.
Documentation
man 2 open
- RETURN VALUE
- ERRORS
Error helper: perror()
int fd = open(path, O_RDONLY); if (-1 == fd) { // fprintf(stderr, "open() failed with error %d\n", errno); perror("open") # perror will interpret errno for you exit(EXIT_FAILURE); }
Full example of errno.c
#include <fcntl.h> // O_RDONLY, open #include <unistd.h> // read, close #include <errno.h> // errno #include <stdio.h> // perror, fprintf #include <stdlib.h> // exit int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "USAGE: %s file\n", argv[0]); exit(1); } char *path = argv[1]; int fd = open(path, O_RDONLY); if (-1 == fd) { perror("open"); exit(1); } if (-1 == close(fd)) { perror("close"); } }
strace ./errno missingfile |& egrep "^(open|exit|close|perror)" strace ./errno files.c |& egrep "^(open|exit|close|perror)"
Notice that exit and perror are not in strace, because these are C library calls. exit wraps a call to exit_group and perror is a user-space function that interprets the errno. Also note that open is implemented by calling the openat syscall, which is another variant of open.
Using file syscalls
Reading Files
Symbol | Reference | Reading |
---|---|---|
open() | man 2 open |
LPI 4.1 |
read() | man 2 read |
|
close() | man 2 close |
Full example of files.c
#include <fcntl.h> // O_RDONLY, open #include <unistd.h> // read, close #include <errno.h> // errno #include <stdio.h> // perror, fprintf #include <stdlib.h> // exit int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "USAGE: %s file\n", argv[0]); exit(1); } char *path = argv[1]; int fd = open(path, O_RDONLY); if (-1 == fd) { perror("open"); exit(1); } const int BUFSIZE = 10; char buf[BUFSIZE]; int bytes = read(fd, buf, BUFSIZE); if (-1 == bytes) { perror("read"); exit(1); } for (int i = 0; i < bytes; i++) { printf("%c", buf[i]); } if (-1 == close(fd)) { perror("close"); } }
Directory Operations
Symbol | Reference | Reading |
---|---|---|
opendir() | man 3 opendir |
LPI 18.8 |
readdir() | man 3 readdir |
|
closedir() | man 3 closedir |
Full example of dir.c
#include <fcntl.h> // O_RDONLY, open #include <unistd.h> // read, close #include <errno.h> // errno #include <stdio.h> // perror, fprintf #include <stdlib.h> // exit #include <dirent.h> // opendir, readdir, DIR, struct dirent int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "USAGE: %s path\n", argv[0]); exit(1); } char *path = argv[1]; DIR *dirp = opendir(path); if (NULL == dirp) { perror("opendir"); exit(EXIT_FAILURE); } struct dirent *curdir; // ls -f should be the same order // why not same order as ls? while ((curdir = readdir(dirp)) != NULL) { printf("%s\n", curdir->d_name); // concatenating path names? } if (-1 == closedir(dirp)) { perror("closedir"); exit(1); } }
File Status
Symbol | Reference | Reading |
---|---|---|
stat() | man 2 stat |
LPI 15.1 |
struct stat | man 3 stat |
|
st_mode | man 7 inode |
Use the stat
command to see what kind of info is stored in the stat
struct.
Full example of stat.c
#include <errno.h> // errno #include <stdio.h> // perror, fprintf #include <stdlib.h> // exit #include <inttypes.h> // PRIdMAX #include <sys/stat.h> // stat int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "USAGE: %s path\n", argv[0]); exit(1); } char *path = argv[1]; struct stat statbuf; if (stat(path, &statbuf) == -1) { perror("stat"); exit(EXIT_FAILURE); } printf("links: %" PRIdMAX "\n", statbuf.st_nlink); printf("size: %" PRIdMAX "\n", statbuf.st_size); switch (statbuf.st_mode & S_IFMT) { case S_IFREG: printf("REG\n"); break; case S_IFDIR: printf("DIR\n"); break; case S_IFSOCK: printf("SOCK\n"); break; case S_IFLNK: printf("LNK\n"); break; case S_IFBLK: printf("BLK\n"); break; case S_IFCHR: printf("CHR\n"); break; case S_IFIFO: printf("FIFO\n"); break; default: // should never happen printf("UNKNOWN\n"); break; } }
If hard links to directories can't be created by the user, where are these hard links from?
From the .. parent directories and subdirectories.
myls Project Overview
Motivating questions
- How to find the number of files in a directory?
- How to tell whether a file is regular or a directory?
- How to check the file mode?