[Linux & Unix -- open/close/write/read System Call], linux operating system
If you have any shortcomings, please kindly advise. Reprinted Please note: @ CSU-Max
Series of blog posts:
Linux and Unix -- file descriptors and permissions
Second play in Linux & Unix Learning -- exec and fock system calls
Linux & Unix -- open/close/write/read system call
In Unix/Linux systems, files are a very important concept. This article will introduce several important file-related system calls in Linux-open-close-write-read system calls.
Open System Call function prototype and interpretation
<Span style = "font-family: Courier New; font-size: 18px;"> <span style = "font-family: Courier New; font-size: 18px; "> // open -- open or create the file int open (const char * path,/* pathname */int flags,/* flags */mode_t perms/* permissions (when creating) */); </span>
You can call open to open an existing file (common file, special file, or named pipe) or create a new file, but it can only create common files (mknod is required to create special files, the named pipe uses mkfifo ). Open returns the file descriptor that opens an existing file or creates a new file. Once a file is opened, the returned file descriptor can be used for read, write, lseek, close, and other calls.
Open an existing file
First, let's take a look at the three parameters of the open function. path is the path of an existing file. As for the flags parameter, if the value is O_RDONLY, the file will be opened in read-only mode, if the value is O_WDONLY, open the file in write-only mode. If the value is O_RDWR, open the file in read/write mode. For an existing file, the perms parameter is useless, it is usually omitted, so in this case, open call requires only two parameters.
There are many causes of open failure. There are two common causes:
1. No corresponding file access permission
2. The file pointed to by the path does not exist.
Create a new file
As mentioned above, when the file does not exist, open will create a new file (only common files). We only need to use the or operation to add the O_CREAT sign to the open flags parameter. In this way, you can create a new read-only file, but this does not make any sense, because the new file does not have any readable content. Therefore, O_CREAT must be used with O_WRONLY or O_RDWR. In this case, the perms parameter is required.
For example:
Ec_neg1 (fd = open ("/home/marc/newfile", O_RDWR | O_CREAT, PERM_FILE ))
The perms parameter is valid only when a new file is created. It does not work for an existing file.
Users sometimes need a new file without any data, that is, when the file already exists, they need to clear all its data and set the file offset to 0. The O_TRUNC flag can implement this function:
Ec_neg1 (fd = open ("/home/marc/newfile", O_WRONLY | O_CREAT | O_TRUNC, PERM_FILE ))
Because O_TRUNC can corrupt data, as long as the process has the write permission, it can clear the data of existing files, because it is a write form. But it does not work for files with the O_RDONLY flag.
O_WRONLY | O_CREAT | this combination of O_TRUNC is very common (creating or truncating a file with write-only permission), as well as dedicated system calls, namely, creat system calls.
Creat system call
<Span style = "font-family: Courier New; font-size: 18px;"> <span style = "font-family: Courier New; font-size: 18px; "> // creat -- create or clear the int creat (const char * path,/* pathname */mode_t perms/* permissions */) file; </span>
To open an existing file using open, you only need the first and second parameters (path and flags ); using creat to create a new file requires only the first and third parameters (path and perms). In fact, creat is just a macro:
# Define creat (path, perms) open (path, O_WRONLY | O_CREAT | O_TRUNC, perms)
Of course, we can also use open instead of creat. However, in the early stage, open only had two parameters, and creat was irreplaceable.
About open flags Parameters
In addition to the open labels described above, there are many open labels, as shown in the following table:
Flag |
Explanation |
O_RDONLY |
Open in read-only mode |
O_WRONLY |
Open in write-only mode |
O_RDWR |
Read/write mode |
O_APPEND |
Each write is appended to the end of the file. |
O_CREAT |
Create a file if the file does not exist. |
O_DSYNC |
Set synchronous I/O mode |
O_EXCL |
If the file already exists, an error occurs. It must be used with O_CREAT. |
O_NOCTTY |
Do not use this device as the control terminal |
O_NONBLOCK |
Do not wait for the named pipe or special file to be ready |
O_RSYNC |
Set synchronous I/O mode |
O_SYNC |
Set synchronous I/O mode |
O_TRUNC |
Truncates the value to 0. |
Prototype and interpretation of the close system call Function
<Span style = "font-family: Courier New; font-size: 18px;"> <span style = "font-family: Courier New; font-size: 18px; "> // close -- close the file descriptor int close (int fd/* file descriptor */); </span>
Through the analysis of close, we will find that close does not do any substantive work, it does not refresh any kernel buffer, but simply makes the file descriptor reusable.
For example, if the description of all open files is disabled, the description of the open files will be deleted. Similarly, when all open file descriptions directed to an information node are deleted, the memory information node is deleted.
Prototype and interpretation of the write System Call Function
<Span style = "font-family: Courier New; font-size: 18px;"> <span style = "font-family: Courier New; font-size: 18px; "> // write -- write ssize_t write (int fd,/* file descriptor */const void * buf to the file descriptor, /* data to write */size_t nbytes/* amount to write */); </span>
The write system calls to write n Bytes of the buffer to which the buf points to the ude described by fd to open the file.
The write operation starts from the current position of the file offset. After the operation is completed, the file offset increases the number of bytes written. If the write is successful, the return value is the number of bytes that have been written, and the error value is-1.
If the O_APPEND flag is set, the file offset before writing is automatically located at the end of the file.
This article only discusses write operations on common files.
Note: write is also used to write data to pipelines, special files, and sockets. However, these write operations may be blocked (for example, they may be waiting for available data ). If the write operation is blocked, the received signal will interrupt the operation. In this case, the write operation returns-1 and errno is set to EINTR.
The true face of write
After reading the previous introduction, write only seems to write data and then return the result. This is not the case. When you call the write system call, you do not perform the write operation, and then return the data. It only transmits the data to the buffer zone of the kernel.
When a write request is received, ensure that the imported file descriptor can be used, and then copy the data to the buffer in the kernel. In the future, the system will try to write this part of data to the disk at a certain convenience. If an error is found, the system tries to output the error in the console, but the process does not return this error (it may have terminated the operation at this time ). If the process or other process tries to read the data before the system writes the data to the disk, the system will read the data from the kernel buffer for you.
All in all, the process does not know when the system has completed the request or whether the request has been completed. If a disk error occurs before the data in the buffer zone is written to the disk, or the kernel is stopped for some reason, you will find that the data to be written is not written to the disk at all, even if the write statement does not return an error.
From this we can see that this is a type of delayed writing. So what do we need to care about delayed writing?
1. You cannot determine when a physical write operation will take place.
2. A process that calls the write operation has not been notified of a write error.
3. The sequence of physical write operations cannot be performed.
Writeall Function
Writeall is a very convenient and practical function that can be used to ensure that all content is written.
<Span style = "font-family: Courier New; font-size: 18px;"> <span style = "font-family: Courier New; font-size: 18px; "> // writeallssize_t writeall (int fd, const void * buf, size_t nbyte) {ssize_t nwritten = 0; // total number of written characters sszie_t n; // number of characters written in each write operation do {if (n = write (fd, & (const char *) buf) [nwriten], nbyte-nwritten )) =-1) {if (errno = EINTR) // when blocking, write continue in a continuous loop; else return-1;} nwritten + = n ;} while (nwritten <nbyte); return nwritten ;}</span> </span>
Read system call function prototype and Explanation
<Span style = "font-family: Courier New; font-size: 18px;"> <span style = "font-family: Courier New; font-size: 18px; "> // read -- read ssize_t read (int fd,/* file descriptor */void * buf, /* address to receive data */size_t nbytes/* amount to read */); </span>
Opposite to write, a read system call Reads n bytes in the buffer referred to by buf from the open file described by fd. Read reads data starting from the current file offset. After the read operation is completed, the file offset increases the number of bytes read. The returned value of read is the number of bytes read, The End mark of the file, or the error Mark-1. The read operation is not affected by the O_APPEND flag.
If the data is no longer in the buffer (due to previous I/O operations), the process must wait for the kernel to get data from the disk.
Like write, read can be blocked when reading data from pipelines, special files, or sockets. In this case, the read operation may be interrupted by a signal. The returned value is-1, and errno is set to EINTR.
Readall Function
Similar to the writeall function, if you need to read all the data, you can call read cyclically. The readall function is a very convenient and practical function.
<Span style = "font-family: Courier New; font-size: 18px;"> <span style = "font-family: Courier New; font-size: 18px; "> // readallssize_t readall (int fd, const void * buf, size_t nbyte) {ssize_t nread = 0; // total number of characters read ssize_t n; // The number of characters read by each read operation do {if (n = read (fd, & (const char *) buf) [nread], nbyte-nread )) =-1) {if (errno = EINTR) // read continue continuously during blocking; else return-1;} nread + = n ;} while (nread <nbyte); return nread ;}</span> </span>
**************************************** ************************
* Reprinted please indicate the source: @ CSU-Max http://blog.csdn.net/csu_max *
**************************************** ************************
How to delete files in linux
If the graphic interface is used, right-click like Windows and choose Delete.
For the character interface, use the rm command.
Rm and the file name of the file you want to delete
Linux Problems
Adduser + username Add User
Passwd user name SET Password
Userdel user name delete user