This article introduces how to use and pay attention to linux File I/O. If you need it, please refer to it.
In Linux, most file I/O only uses five functions: open, read, write, lseek, and close. The functions involved in this topic are called I/O without buffering. without buffering, the read or read functions are implemented through a kernel system call, these are components of POSIX.1 and Single UNIX Specification. We will further discuss file sharing among multiple processes and the kernel data structure involved.
File descriptor
The file descriptor is a non-negative integer. When open or create is used, a file descriptor is returned to identify the file and can be passed as a parameter to read or write. File descriptor 0 (symbolic constant: STDIN_FILENO) is associated with the standard input of the process. file descriptor 1 (symbolic constant: STDOUT_FILENO) is associated with the standard output of the process, file descriptor 2 (symbolic constant: STDERR_FILENO) is associated with the standard output of the process. These constants are defined in <unistd. h>. The file descriptor ranges from 0 ~ The values of OPEN_MAX and OPEN_MAX can be obtained by calling sysconf (_ SC _OPEN_MAX) through a function. The following is an example:
# Include <stdio. h>
# Include <unistd. h>
Int
Main (void)
{
Long open_max = sysconf (_ SC _OPEN_MAX );
Printf ("% dn", open_max );
Return 0;
}
Output: 1024
Open Function
# Include <fcntl. h>
Int open (const char * pathname, int oflag,.../* mode_t mode */);
The "or" operation is performed on one or more constants to form the oflag parameter (these constants are defined in <fcntl. h> ):
The three constants O_RDONLY, O_WRONLY, and O_RDWR must and can only be specified.
You can select one or more of the following constants:
Append O_APPEND to the end of the file
O_CREAT: if this file does not exist, it is created. When this option is used, the mode parameter is used to set the access permission for the new file.
O_EXCL to test whether a file exists.
O_TRUNC if the file is successfully opened, its length is truncated to 0.
O_NOCTTY if the pathname parameter refers to a terminal device, the device is not used as the control terminal for this process.
O_NONBLOCK if pathname refers to a FIFO, block special file or character special file, this option sets the non-blocking mode for this open operation of the file and subsequent I/O operations.
Note: * non-blocking mode: When the I/O operation cannot be completed, an error occurs immediately and an error is returned, rather than waiting forever.
O_DSYNC waits for all write operations on the file until all I/O operations on the file are completed. However, if the write operation does not affect reading the data just written, you do not have to wait for the file attribute to be updated.
O_RSYNC waits for all the read operations on the file until all the write operations on the file are completed.
O_SYNC waits for all write operations on the file until all I/O operations on the file are completed.
Note: * Linux2.4.22 processes O_DSYNC and O_RSYNC as the same as O_SYNC, that is, the data and attributes of files are always updated synchronously.
Close Function
# Include <unistd. h>
Int close (int file_des );
When a file is closed, all record locks on the file are released. When a process is terminated, the kernel automatically closes all files it opens, but it is safer to explicitly call the close function.
Lseek Function
# Include <unistd. h>
Off_t lseek (int file_des, off_t offset, int whence );
Whence value:
SEEK_SET sets the read/write offset of the file to the first offset byte of the file.
SEEK_CUR sets the read/write offset of the file to a byte between the current value and the offset value. The offset value can be positive or negative.
SEEK_END sets the file's read/write offset to one byte from the end of the file, and the offset value can be positive or negative.
Return the new file offset when the operation succeeds, and-1 if the operation fails. The return value can be used to test whether the file descriptor can set the read/write offset (the offset cannot be set for pipelines, FIFO, and network sockets ). When the read/write offset is greater than the file length, the write operation will create a hole in the file. The empty space is read as 0, but the empty space does not occupy disk space, the processing method is related to the implementation of the file system. The following program creates an empty file:
# Include <unistd. h>
# Include <stdlib. h>
# Include <stdio. h>
# Include <fcntl. h>
# Include <string. h>
Char buf [] = "1234567890 ";
Char buf2 [] = "abcdefghij ";
Int
Main (void)
{
Remove ("file. hole ");
Int file_des = open ("file. hole", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IXUSR );
If (file_des =-1)
{
Write (STDOUT_FILENO, "open file error! N ", 20 );
Exit (0 );
}
If (lseek (file_des, 5, SEEK_SET) =-1)
{
Write (STDOUT_FILENO, "first seek error! N ", 20 );
Exit (0 );
}
Size_t write_bytes = write (file_des, buf, strlen (buf ));
If (write_bytes <strlen (buf ))
{
Write (STDOUT_FILENO, "first write error! N ", 20 );
Exit (0 );
}
If (lseek (file_des, 5, SEEK_END) =-1)
{
Write (STDOUT_FILENO, "second seek error! N ", 20 );
Exit (0 );
}
Write_bytes = write (file_des, buf2, strlen (buf ));
If (write_bytes <strlen (buf2 ))
{
Write (STDOUT_FILENO, "second write error! ", 20 );
Exit (0 );
}
Close (file_des );
Return 0;
}
Use the command od to view the file. hole content:
[Root @ localhost CC ++] # od-c file. hole
0000000 1 2 3 4 5 6 7 8 9 0
0000020 a B c d e f g h I j
We can see that there is a hole at the beginning of the file, and there is a hole in the middle, all of which are read as 0.
Read and write Functions:
# Include <unistd. h>
Ssize_t read (int file_des, void * buf, size_t nbytes );
Returned value: the number of bytes read successfully. If 0 is returned to the end of the file,-1 is returned for an error.
Ssize_t write (int file_des, const void * size_t, size_t nbytes );
Returned value: the number of written bytes is returned successfully, and-1 is returned if an error occurs.
Pread and pwrite functions:
# Include <unistd. h>
Ssize_t pread (int file_des, void * buf, size_t nbytes, off_t off_set );
Ssize_t pwrite (int file_des, const void * buf, size_t nbytes, off_t off_set );
Note: * The pread and pwrite functions make the lseek and read/write operations an atomic operation. The important differences between pread/pwrite and lseek/read/write are:
When pread/pwrite is called, positioning and read (write) operations cannot be interrupted;
Pread/pwrite cannot update file pointers. You can use the ftell or fgetpos function to obtain the current read/write location.
Dup and dup2 functions:
# Include <unistd. h>
Int dup (int file_des );
Int dup2 (int file_des, int file_des2 );
Both dup and dup2 are used to copy an existing file descriptor, and a new file descriptor is returned successfully. If an error occurs,-1 is returned. The difference is:
Dup must return the currently available minimum file descriptor;
Dup2 specifies that the parameter file_des2 is a new file descriptor. When file_des2 is enabled, disable it first. If file_des is equal to file_des2, file_des2 is returned instead of closed.
Note: * The fcntl function can also copy the file descriptor, which will be introduced later.
Sync, fsync, and fdatasync functions:
# Include <unistd. h>
Int sync (void );
Int fsync (int file_des );
Int fdatasync (int file_des );
All the above functions are used to ensure consistency between physical files and cache data. The difference is that sync only queues all modified block buffers into the write queue and returns the data without waiting for the completion of disk write operations; fsync only targets a single file pointed to by the file descriptor, and waits for the disk write operation to be completed before returning, but it only affects the data part of the file; fdatasync is similar to fsync, but apart from data, fdatasync also synchronously updates the attributes of the file.
Fcntl function:
# Include <fcntl. h>
Int fcntl (int files_des, int cmd,.../* int arg */);
The fcntl function can change the nature of opened files.
Cmd parameter values (10 in total, the first seven types are introduced here ):
F_DUPFD: copy the file descriptor files_des. The new file descriptor is returned as the function return value. The new descriptor has its own file descriptor identifier, and its FD_CLOEXEC file descriptor identifier is cleared.
F_GETFD corresponds to the file descriptor flag of files_des and is returned as a function value. Currently, only one file descriptor flag FD_CLOEXEC is defined.
F_SETFD sets the file descriptor flag for files_des. The new flag value is set according to the third parameter.
F_GETFL corresponds to the file status flag of files_des and is returned as a function value. The file status flag has been described in the open function.
F_SETFL sets the File status flag to the value of the third parameter. The following flags can be changed: O_APPEND, O_NONBLOCK, O_SYNC, O_DSYNC, O_RSYNC, O_FSYNC, and 0_ASYNC.
F_GETOWN: process ID or process lease ID that receives SIGIO and SIGURG signals.
F_SETOWN: set the process ID or process lease ID that receives SIGIO and SIGURG signals. The positive arg parameter indicates a process ID, and the negative arg parameter indicates the process lease ID that is equal to the absolute value of arg.