Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced Unix Programming

Similar presentations


Presentation on theme: "Advanced Unix Programming"— Presentation transcript:

1 Advanced Unix Programming
Chapter 3 – File I/O Part 2

2 Open file representation
Kernel uses three data structures to represent an open file Process table contains table of open file descriptors A file table for each open file v-node structure

3 File Descriptor table Process table has a file descriptor table
Each file descriptor entry contains: File descriptor flags (close-on-exec) Pointer to File table entry File descriptor value is used as the index in the file descriptor table See Figure 3.6 of CB (sec. 3.10)

4 File Table Entry Kernel maintains a file table entry for each open file File Table entry has: File status flags (corresponds to oflag parameter of open): e.g. O_RDONLY, O_WRONLY, O_APPEND, O_SYNC Current file offset Pointer to v-node table entry See figure 3.6 again

5 v-node table entry Linux uses generic i-node. But v-node conceptually same as generic i-node v-node entry has: Pointers to function that operate of file i-node of file (for most files). i-node has owner of file, size of file, location of data blocks on disk See figure 3.6 (two separate files are open)

6 Two processes – same file
Two independent processes could have the same file opened See figure 3.7 Each process has its own file table entry and so its own current file offset Both file table entries point to same v-node table entry

7 Kernel file structures …
This knowledge will help us understand some system calls which we will be studying later. Course book also explains effect of some system calls like write, lseek, O_APPEND flag in the context of the kernel file structures. Please read if possible 

8 Atomic Operations Appending to file was earlier done without O_APPEND as follows: if (lseek(fd, 0L, 2) < 0) /* position to EOF */ err_sys("lseek error"); if (write(fd, buf, 100) != 100) /* and write */ err_sys("write error");

9 Without O_APPEND … Code shown earlier works OK for single process
If multiple process write to same file the code may not work. E.g. Two processes may be writing to a log file. Process A and B appending to same file. Scenario is similar to figure 3.7 A and B have separate file table entry but same v-node table entry

10 Without O_APPEND Process A does lseek to end. Sets its current file offset to end of file, say, 1500. Kernel switches processes (before A can proceed to write) Process B then does lseek to end. Sets its current file offset to end of file, 1500. B calls write (100 bytes). Now B’s current file offset is v-node entry file size is also 1600

11 Without O_APPEND … Now kernel switches to process A.
A resumes and calls write. Data is written starting at current file offset for A which is 1500. This overwrites data that process B wrote.

12 Problem without O_APPEND
Logical operation of position to end of file and write requires two system (function) calls. A system call is an atomic operation with regard to other processes But kernel can always switch to another process between two system calls

13 Solution Solution is to have a single system call which does both operations (position to end of file and write) File opened with O_APPEND set results in write system call doing both operations write being a system call is atomic and thus the problem is solved.

14 Creation of file We need code to create a logfile.
A logfile can be created by any one of multiple processes which are logging to the file. But logfile should be created only if it does not exist. Otherwise the log entry should be appended to existing logfile.

15 Code for creation of log file
if ((fd = open(pathname, O_WRONLY)) < 0) { if (errno == ENOENT) { if ((fd = creat(pathname, mode)) < 0) err_sys("creat error"); } else { err_sys("open error"); }

16 Atomic problem Process A attempts open of log file
Open fails and before next instruction is executed kernel switches to process B. Process B attempts open of same log file Open fails and process B creates log file. B writes to log file (code not shown) Kernel switches to Process A

17 Atomic problem Process A resumes.
It executes if statement checking errno Process A process to create log file creat on existing file truncates file to 0 bytes Process B’s log entry is lost Process A proceeds to write its log entry. Nobody even knows about Process B’s log entry being lost. Hidden problem – Most difficult class of bugs. Can cause enormous loss and damage.

18 Solution Combine test for existence and creation into single operation solves the problem Use open with O_CREAT | O_EXCL If file does not exist - Creates file. If file exists - Generates error Open with O_CREAT only If file exists – Truncates file to 0 bytes and opens file

19 if ((fd = open(pathname, O_WRONLY)) < 0) {
if (errno == ENOENT) { if ((fd = open(pathname, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { if (errno == ???) { //created by another proc. //Proceed to open file …. } else { // some other error, bail out err_sys("creat error"); } } else { err_sys("open error");

20 Atomic Operation In general, atomic operation may be composed of multiple steps If operation is performed atomically then Either all steps are performed Or no steps (none) are performed It must not be possible for a subset of steps to be performed.

21 Assignment Do assignment 3B from course web page
Ensure that you test atomic operation by setting breakpoint traps and creating conditions similar to that discussed in earlier slides.

22 Self Study dup – duplicates a file descriptor (Will come back to it later on in the course) fsync – Writes data to disk before returning. Useful for database programs. fcntl – Can view properties of file (Open flags) and also change them for an open file. ioctl – catchall function for I/O operations, low level function. /dev/fd


Download ppt "Advanced Unix Programming"

Similar presentations


Ads by Google