ThursdayClass TuesdayClass ThursdayClass
Unix uses device independence.
I/O is done through device drivers that have a standard interface.
5 main system calls for I/O:
Figure 3.2 (page 86): Structure of a typical UNIX filesystem
Current Working Directory
#include <unistd.h> char *getcwd(char *buf, size_t size);Example 3.2 (page 80) outputs the pathname of the current working directory. It uses PATH_MAX to determine the size of the buffer needed.
Example 3.3 (page 81) determines the implementation's maximum pathname length relative to the root directory using pathconf.
Reading Directories
#include <sys/types.hi> #include <dirent.h> DIR *opendir(const char *filename); struct dirent *readdir(DIR *dirp); void rewinddir(DIR *dirp); int closedir(DIR *dirp);opendir provides a handle for the other functions.
Program 3.1 (page 83) lists the files in a directory.
Inodes
A directory entry contains only a name and an index into a table
giving information about a file. The table and the index are both
referred to as an inode.
This is what an inode looks like:
Figure 3.3 (page 87): Inodes are used to represent information about a UNIX file.
Inodes are read using the system call stat
#include <sys/types.h> #include <sys/stat.h> int stat(const char *path, struct stat *buf); int fstat(int fildes, struct stat *buf); int lstat(const char *path, struct stat *buf);stat is given the name of a file.
dev_t st_dev; /* ID of device containing directory entry */ ino_t st_ino; /* Inode number */ mode_t st_mode; /* File mode (type and permissions) */ nlink_t st_nlink; /* Number of links */ uid_t st_uid; /* User ID of the file's owner */ gid_t st_gid; /* Group ID of the file's group */ dev_t st_rdev; /* ID for special files */ off_t st_size; /* File size in bytes */ timestruc_t st_atim; /* Time of last access */ timestruc_t st_mtim; /* Time of last data modification */ timestruc_t st_ctim; /* Time of last file status change */ blksize_t st_blksize; /* Preferred I/O block size */ blkcnt_t st_blocks; /* Number st_blksize blocks allocated */The timestruc_t is the same as the struct timespec structure which contains two fields:
time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */Example 3.6 (page 89) takes a directory name passed on the command line and lists the contents of that directory along with the time it was last modified.
Links
Figure 3.4 (page 91): A directory entry, inode, and data block for a simple file. | Figure 3.5 (page 92): Two hard links to the same file as in Figure 3.4. |
Figure 3.5 (page 92): Two hard links to the same file as in Figure 3.4. | Figure 3.6 (page 93): The situation after editing the file. The original file had inode 12345 and two hard links prior to being edited. |
Figure 3.5 (page 92): Two hard links to the same file as in Figure 3.4. | Figure 3.7 (page 93): The situation after editing the file with an editor that makes a backup copy. |
How to do it right:
open("/dirA/name1");
read
close
modify memory image file file
open("/dirA/name1",O_WRONLY|O_TRUNC);
write
close
Symbolic Links
Figure 3.8 (page 94): An ordinary file with a symbolic link to it.
Figure 3.9 (page 95): The situation after editing a file that has a symbolic link.
File Handles
Two methods of doing I/O in UNIX:
File descriptors: this is part of the UNIX specification, POSIX, etc.
File pointers: this is from the C standard
File Descriptors
Use the POSIX names STDIN_FILENO,
STDOUT_FILENO and STDERR_FILENO.
open, close, read, write,ioctl
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *path, int oflag, ...);Common oflag values: O_RDONLY O_WRONLY O_RDWR O_CREAT
Figure 3.10 (page 98): The layout of the permissions mask.
S_IRUSR | read permission bit for owner |
S_IWUSR | write permission bit for owner |
S_IXUSR | execute permission bit for owner |
S_IRWXU | read, write, execute for owner |
S_IRGRP | read permission bit for group |
S_IWGRP | write permission bit for group |
S_IXGRP | execute permission bit for group |
S_IRWXG | read, write, execute for group |
S_IROTH | read permission bit for others |
S_IWOTH | write permission bit for others |
S_IXOTH | execute permission bit for others |
S_IRWXO | read, write, execute for others |
S_ISUID | set user ID on execution |
S_ISGID | set group ID on execution |
Table 3.1, Page 99: POSIX.1 symbolic names for file permission bits.
Example 3.10 (page 98) show simple code to create a new file.
Figure 3.11 (page 100): Relationship between the file descriptor table, the system file table and the in-memory inode table.
File Pointers and Buffering
Use fopen, fclose, fread, fwrite, fprintf, fscanf, etc.
Example 3.11 (page 101) shows how to open a file file output using file
pointers.
Figure 3.12 (page 102): Schematic use of a file pointer after fopen.
Inheritance of File Descriptors
When fork creates a child, the child inherits a copy of the
parents address space, including the file descriptor table.
Example 3.14 (pages 103-104) shows a code segment in which a child inherits
a file descriptor of an open file.
Figure 3.13 (page 105) shows the file descriptor tables and system file table
corresponding to this code.
Figure 3.13 (page 105): If the parent opens my.dat before the fork, both parent and child share the system file table entry.
Figure 3.14 (page 106): If the parent and child open my.dat after the fork, the two processes use different system file table entries.
Figure 3.15 (page 107): The status of the file descriptor table before and after redirection for the process that is executing cat > my.file
Redirection can be done by copying one entry of the file descriptor table
into another.
This is accomplished with the dup2 system call.
#include <udistd.h> int dup2(int fildes, int fildes2);It closes fildes2 and then copies the pointer of entry fildes into the entry fildes2.
Pipes
From the command line:
ls -l | sort -nr +4 | head
produces a list of files sorted by size with only the largest ones displayed.
This is done with the pipe system call:
#include <unistd.h> int pipe(int fildes[2]);
Figures 3.18 to 3.20 (pages 111-112) show the state of the file descriptor table for Example 3.20.
Figure 3.18 (page 111): The status of the file descriptor table after the fork has been executed in Example 3.20.
Figure 3.19 (page 112): The status of the file descriptor table after the pup2's have been executed in both processes of Example 3.20.
Figure 3.20 (page 112): The status of the file descriptor table just before the execl's have been executed in both processes of Example 3.20.
read and write
#include <unistd.h> ssize_t read(int fildes, void *buf, size_t nbyte); ssize_t write(int fildes, const void *buf, size_t nbyte);
This code is not correct since it is not guaranteed that the write will actually write all of the bytes that it is requested to write.
Program 3.2 (pages 114-115) show how to do this correctly.
The program takes source and destination as command line parameters.
An error occurs if the destination file already exists.
A loop for the write handles the case of partial writes.
Non-blocking I/O Various control flags can be changed using fcntl:
#include <sys/types.h> #include <unistd.h> #include <fcntl.h> int fcntl(int fildes, int cmd, /* arg */ ...);Example 3.22 (page 116) is a program segment that sets an open file descriptor to non-blocking.
You can use non-blocking I/O to monitor 2 file descriptors, but this solution
uses busy waiting.
select
#include <sys/time.h> #include <sys/types.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); void FD_SET(int fd, fd_set *fdset); void FD_CLR(int fd, fd_set *fdset); int FD_ISSET(int fd, fd_set *fdset); void FD_ZERO(fd_set *fdset);Example 3.24 (pages 118-119) shows how to use this to monitor two file descriptors.
FIFOs
FIFOs, or named pipes allow you to use pipes between processes that are
not related.
You can create a named pipe with the mkfifo command or the
mkfifo system call.
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *path, mode_t mode);The programs readfifo and writefifo illustrate how these can be used.
Get readfifo.c or writefifo.c.
Note: There is something wrong with these programs. What is it?