《Unix高级环境编程》 读书笔记(2)(ch3~ch6)

来源:互联网 发布:php求素数 编辑:程序博客网 时间:2024/06/13 18:28

to be continued···

chapter 3 File I/O


3.1 Introduction

    We'll start our discussion of the UNIX System by describing the functions available for file I/Oopen a file, read a file, write a file, and so on. Most file I/O on a UNIX system can be performed using only five functions: open, read, write, lseek, andclose. We then examine the effect of various buffer sizes on theread andwrite functions.

     The functions described in this chapter are often referred to asunbuffered I/O, in contrast to the standard I/O routines, which we describe inChapter 5.The term unbuffered means that each read or write invokes a system call in the kernel. These unbuffered I/O functions are not part of ISO C, butare part of POSIX.1 and the Single UNIX Specification.

     Whenever we describe the sharing of resources among multiple processes, the concept of anatomic operationbecomes important. We examine this concept with regard to file I/O and the arguments to theopen function. This leads to a discussion of how files are shared among multiple processes and the kernel data structures involved. After describing these features, we describe thedup, fcntl, sync, fsync, and ioctl functions.


3.2 File Descriptor

    文件描述符是kernel在打开。创建文件时生成的文件标示。

   To the kernel, all open files are referred to by file descriptors. A file descriptor is a non-negative integer. When we open an existing file or create a new file, the kernel returns a file descriptor to the process. When we want to read or write a file, we identify the file with the file descriptor that was returned byopen orcreat as an argument to either read or write.

By convention, UNIX System shells associate file descriptor 0 with the standard input of a process, file descriptor 1 with the standard output, and file descriptor 2 with the standard error. This convention is used by the shells and many applications; it is not a feature of the UNIX kernel. Nevertheless, many applications would break if these associations weren't followed.

The magic numbers 0, 1, and 2 should be replaced in POSIX-compliant applications with the symbolic constantsSTDIN_FILENO,STDOUT_FILENO, and STDERR_FILENO. These constants are defined in the<unistd.h> header.

File descriptors range from 0 throughOPEN_MAX. (Linux 2.4.22 places a hard limit of 1,048,576 on the number of file descriptors per process.)

3.3 open Function

A file is opened or vreated by calling the open function.

#include <fcntl.h>int open(const char *pathname, int oflag, ... /* mode_t mode   */ );

Returns: file descriptor if OK, 1 on error

We show the third argument as ..., which is the ISO C way to specify that the number and types of the remaining arguments may vary. For this function, the third argument is used only when a new file is being created, as we describe later. We show this argument as a comment in the prototype.

The pathname is the name of the file to open or create.This function has a multitude of options, which are specified by the oflag argument. This argument is formed by ORing together one or more of the following constants from the<fcntl.h> header:

O_RDONLY

Open for reading only.

O_WRONLY

Open for writing only.

O_RDWR

Open for reading and writing.

以上者三个中需要要选择一个(且仅一个)。以下还有一些可选项。One and only one of these three constants must be specified. The following constants are optional:

O_APPEND

Append to the end of file on each write. We describe this option in detail inSection 3.11.

O_CREAT

Create the file if it doesn't exist. This option requires a third argument to theopen function, the mode, which specifies the access permission bits of the new file. (When we describe a file's access permission bits inSection 4.5, we'll see how to specify themode and how it can be modified by the umask value of a process.)

O_EXCL

Generate an error if O_CREAT is also specified and the file already exists. This test for whether the file already exists and the creation of the file if it doesn't exist is an atomic operation. We describe atomic operations in more detail in Section 3.11.

O_TRUNC

If the file exists and if it is successfully opened for either write-only or readwrite, truncate its length to 0.

O_NOCTTY

If the pathname refers to a terminal device, do not allocate the device as the controlling terminal for this process. We talk about controlling terminals inSection 9.6.

O_NONBLOCK

If the pathname refers to a FIFO, a block special file, or a character special file, this option sets the nonblocking mode for both the opening of the file and subsequent I/O. We describe this mode inSection 14.2.

     以及一些读写时同步的问题。The following three flags are also optional. They are part of the synchronized input and output option of the Single UNIX Specification (and thus POSIX.1):

O_DSYNC

Have each write wait for physical I/O to complete, but don't wait for file attributes to be updated if they don't affect the ability to read the data just written.

O_RSYNC

Have each read operation on the file descriptor wait until any pending writes for the same portion of the file are complete.

O_SYNC

Have each write wait for physical I/O to complete, including I/O necessary to update file attributes modified as a result of thewrite. We use this option in Section 3.14.

3.4 creat function

A new file can also be created by calling the creat function.

#include <fcntl.h>int creat(const char *pathname, mode_t mode);

Returns: file descriptor opened for write-only if OK, 1 on error

Note that this function is equivalent to 
   open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
One deficiency with creat is that the file is opened only for writing. Before the new version ofopen was provided, if we were creating a temporary file that we wanted to write and then read back, we had to callcreat,close, and thenopen. A better way is to use theopen function, as in
    open (pathname, O_RDWR | O_CREAT | O_TRUNC, mode);
3.5 close function

An open file is closed by calling the close function.

#include <unistd.h>int close(int filedes);

Returns: 0 if OK, 1 on error


Closing a file also releases any record locks that the process may have on the file.

When a process terminates, all of its open files are closed automatically by the kernel.Many programs take advantage of this fact and don't explicitly close open files.

3.6 lseek function

      Every open file has an associated "current file offset," normally a non-negative integer thatmeasures the number of bytes from the beginning of the file. (We describe some exceptions to the "non-negative" qualifier later in this section.)Read and write operations normally start at the current file offset and cause the offset to be incremented by the number of bytes read or written. By default, this offset is initialized to 0 when a file is opened, unless theO_APPEND option is specified.

An open file's offset can be set explicitly by calling lseek.

#include <unistd.h>off_t lseek(int filedes, off_t offset, int whence);

Returns: new file offset if OK, 1 on error

The interpretation of theoffset depends on the value of the whence argument.

  • If whence is SEEK_SET, the file's offset is set tooffset bytes from the beginning of the file.

  • If whence is SEEK_CUR, the file's offset is set to its current value plus theoffset. The offset can be positive or negative.

  • If whence is SEEK_END, the file's offset is set to the size of the file plus theoffset. The offset can be positive or negative.

Because a successful call to lseek returns the new file offset, we can seek zero bytes from the current position to determine the current offset:

    off_t    currpos;    currpos = lseek(fd, 0, SEEK_CUR);

This technique can also be used to determine if a file is capable of seeking. If the file descriptor refers to a pipe, FIFO, or socket,lseek sets errno to ESPIPE and returns 1.

(The character l in the name lseek means "long integer." Before the introduction of theoff_t data type, the offset argument and the return value were long integers.lseek was introduced with Version 7 when long integers were added to C. )