1 / 24

File descriptors and I/O efficiency in Unix

Learn about file descriptors, file I/O efficiency, file sharing, and atomic operations in the Unix operating system. Explore functions like open(), creat(), and lseek(), and understand how to optimize I/O efficiency.

boutin
Download Presentation

File descriptors and I/O efficiency in Unix

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. FILE I/O • File Descriptors • I/O Efficiency • File Sharing • Atomic Operations Nittida

  2. File Descriptors • Tokernel all open files are referred by file descriptors • A file descriptor • a non-negative integer • returned by the kernel (to a process) when a file is opened or created • is used to identify a file (to be accessed) as an argument to read or write functions • By convention, the Unix shells associate file descriptor • 0 with the standard input of a process • 1 with the standard output • 2 with the standard error • File descriptors range from 0 to OPEN_MAX (defined in <limits.h>) Nittida

  3. File Descriptors • open() function • #include <sys/types.h> • #include <sys/stat.h> • #include <fcntl.h> • int open(const char *pathname, int oflag, … /*, mode_t mode */); • Returns: file descriptor if OK, -1 on error • oflag :defined in <fcntl.h> • O_RDONLY, O_WRONLY, O_RDWR (one and only one of these) • and optional constants from O_APPEND, O_CREATE, O_EXCL, • O_TRUNC, O_SYNC, etc Nittida

  4. File Descriptors • creat() function • #include <sys/types.h> • #include <sys/stat.h> • #include <fcntl.h> • int creat(const char *pathname, mode_t mode); • Returns: file descriptor opened for write only if OK, -1 on error Nittida

  5. File Descriptors • One defficiency with creat() is • the file is opened for writing • if we need to write/read • creat () , close (), open () • A better way is open (pathname, O_RDWR|O_CREAT|O_TRUNC, mode); Nittida

  6. lseek() Function File Descriptors • #include <sys/types.h> • #include <unistd.h> • off_t lseek(int fliedes, off_t offset, int whence); • Returns: new file offset if OK, -1 on error whence : SEEK_SET -- offset bytes from the beginning of the file SEEK_CUR -- current value + offset SEEK_END -- size of the file + offset Nittida

  7. File Descriptors We can seek zero bytes from the current position to determine the current offset offt_t curpos; curpos = lseek(fd, 0, SEEK_CUR); • The techinique is used to determine if the file is capable of seeking: • if the fd is referred to a pipe or FIFO, lseek will return -1 Nittida

  8. File Descriptors Example #include <sys/types.h> main() { if (lseek(STDIN_FILENO, 0, SEEK_CUR) == -1) printf(“cannot seek\n); else printf(“seek OK\n); exit(0); } (Test if standard input is capable of seeking) Nittida

  9. File Descriptors • If we invoke this program interactively, we get • $ a.out < /etc/motd seek Ok • $ cat < /etc/motd | a.out cannot seek • $ a.out < /var/spool//cron/FIFO cannot seek Nittida

  10. File Descriptors • When lseek() is called, it only records the current file offset within the kernel -- it does not cause any I/O to take place • This offset is then used by the next read or write operation • The file’s offset can be greater than the file’s size, in which case the next write to the file will extend the file • This is referred to as creating a hole in a file and is allowed • Any bytes in a file that have not been written are read back as 0 Nittida

  11. File Descriptors (Small) Home Work • Write a program to create a file with a hole in it…. • Run your program and demonstrate that it works properly by using these commands • ls -l file.hole (if your output file is named file.hole) • (to check the size of the file, which must be the same as the number of characters written by the program) • od -c file.hole • to look at the actual contentx • Due : 8/12/2543 Nittida

  12. I/O Efficiency #include <unistd.h> #define BUFFSIZ 16 int main(void) { int n; char buf[BUFFSIZ]; while ((n = read(STDIN_FILENO, buf, BUFFSIZ)) > 0) if (write(STDOUT_FILENO, buf, n) != n) perror(“Write Error”); if (n < 0) perror (“Read Error”); exit(0); } Nittida

  13. I/O Efficiency • This example works for both text file and binary files, since there is no difference between the two to the Unix kernel • Modify and Run the program using different values for BUFFSIZ (start from 1, 2, 4, 8, 16, …. ,131072) then show the results of reading a big file ( /kernel/genunix on maliwan) -- redirect your output to /dev/null • Time your program everytime and record the required values in the following table. • Are there any differences between the result each time? • What is/are the causes of this differences (if any)? Nittida

  14. I/O Efficiency Run your program and fill in the table….. Nittida

  15. File Sharing • Unix supports the sharing of open files between different processes (based on the basic features as ) • Several structures provided (& used) by the kernel are: 1. Every process has an entry in the process table • within each process table entry is a table of open file descriptors • file descriptor flags • a pointer to a file table entry Nittida

  16. File Sharing 2. The kernel maintains a file table for all open files Each file table entry contains - the file status flag for the file (read, write, etc.) - the current file offset - a pointer to the v-node table entry for the file Nittida

  17. File Sharing 3. Each open file has a v-nodestructure • The v-node contains information about the type of the file and pointers to functions that operate on the file • It also contains other information such as the inode • This information is read from disk when the file is opened Nittida

  18. File Sharing • Kernel data structures for open files Nittida

  19. File Sharing • Two independent processes with the same file open Nittida

  20. File Sharing • What happens with some certain operations • After each write is complete, the current file offset in the file table entry is incremented by number of bytes written • If this causes the current file offset to exceed the current file size, the current file size in the inode table entry is set to the current file offset (the file is extended) • If a file is opened with the O_APPEND flag, a corresponding flag is set in the file status flag of the file table entry • Each time a write is performed for a file with this append flag set, the current file offset in the file table entry is first set to the current file size from the inode table entry Nittida

  21. File Sharing • The lseek function only modifies the current file offset in the file table entry. No I/O takes place • If a file is positioned to its end of file using lseek, all that happens is the current file offset in the file table entry is set to the current file size from the inode table entry Nittida

  22. Atomic Operations • When multiple processes write to the same file, it is possible that unexpected results can arise • Consider if (lseek(fd, 0L, 2) < 0) /*position to EOF */ perror(“lseek error”); if (write(fd, buff, 100) != 100) /* and write */ perror(“write error”); Nittida

  23. Atomic Operations if ( (fd = open(pathname, O_WRONLY)) < 0) if (errno == ENOENT) { if ( (fd = creat(pathname, mode)) < 0) perror (“create error”); } else perror(“open error”); Nittida

  24. Atomic Operations • Atomic operation method is required to solve this problem ---- > • an operation that is composed of multiple steps • if the operation is performed atomically, either all the steps are performed, or none is performed • it must not be possible for a subset of the steps to be performed Nittida

More Related