1.dup and DUP2 functions
#include <unistd.h>
int dup (int fd);
int dup2 (int fd1,int fd2);
Two is a description of the copy of an existing file
Two function return: If the new file is successfully described, if the error is-1;
The new file descriptor returned by the DUP must be the smallest value in the currently available file description. With dup2, you can specify a new descriptor value with the FD2 parameter. If the FD2 is already open, close it first. If FD1=FD2, DUP2 returns FD2 without closing it. Typically, these two system redirects are used to redirect an open file descriptor.
Another way to copy a descriptor is to use the FCNTL function, which is described in the next section. As a matter of fact
Call:
DUP (filedes);
Equivalent to: Fcntl (filedes, F_DUPFD, 0);
Instead, call:
Dup2 (Filedes, Filedes, 2);
is equivalent to:
Close (Filedes2);
Fcntl (Filedes, F_DUPFD, filedes2);
In the last case, dup2 is not exactly the same as close plus fcntl. The difference between them is:
(1) dup2 is an atomic operation, while close and fcntl consist of two function calls. It's possible between close and fcntl.
Insert the Execute signal capture function, which may modify the file descriptor.
(2) There are some different errno between Dup2 and Fcntl.
2. Manipulate the characteristics of the file according to the file description. Fcntl
#include <unistd.h>
#include <fcntl.h>
int fcntl (int fd, int cmd);
int fcntl (int fd, int cmd, long arg);
int fcntl (int fd, int cmd, struct flock *lock);
FCNTL () provides control over (file) descriptors. The parameter FD is a descriptor of the parameter CMD operation (as described below). For a value of CMD, Fcntl can accept the third argument, int arg.
The return value of Fcntl () is related to the command. If there is an error, all commands return-1, and if successful, some other value is returned. The following three commands have specific return values: F_DUPFD, F_GETFD, F_GETFL, and F_getown.
There are five functions of the FCNTL function:
• Copy an existing descriptor (cmd =F_DUPFD).
• Get/Set file descriptor tokens (cmd = F_GETFD or F_SETFD).
• Get/Set file status flag (cmd = F_GETFL or F_SETFL).
• Get/Set asynchronous I/o permissions (cmd = F_getown or F_setown).
• Get/Set record lock (cmd = f_getlk, f_setlk or f_setlkw).
1. F_DUPFD of the CMD value:
F_DUPFD returns a (file) descriptor as described below:
• A minimum of one of the available descriptors greater than or equal to ARG
• Reference to an object like the original operator
• If the object is a file, a new descriptor is returned that shares the same offset as ARG (offset)
• Same access mode (read, write or read/write)
• Same file status flag (e.g.: Two file descriptors share the same status flag)
• The CLOSE-ON-EXEC flag that is combined with the new file descriptor is set as a system call for cross-access Execve (2)
2. F_getfd and f_setfd of the CMD value:
F_GETFD obtains the CLOSE-ON-EXEC flag associated with the file descriptor FD, similar to fd_cloexec. If the return value and Fd_cloexec are 0, the file remains interleaved with exec (), otherwise the file will be closed (Arg ignored) if it is run through exec
F_SETFD sets the CLOSE-ON-EXEC flag, which is determined by the fd_cloexec bit of the parameter arg, and it should be understood that many of the existing programs involving file descriptor flags do not use constant fd_cloexec, but instead set this flag to 0 (system default, Do not close at exec) or 1 (off at exec)
Caution must be taken when modifying the file descriptor flag or file status flag to obtain the current flag value, then modify it as desired, and finally set the new flag value. You cannot just execute the F_SETFD or F_SETFL command, which turns off the previously set flag bit.
3. F_GETFL and F_SETFL of the CMD value:
F_GETFL obtains the file status flag of FD, as described below (ARG is ignored), when describing the open function, it is stated
The file status flag. Unfortunately, three access-mode flags (O_rdonly, o_wronly, and O_RDWR) do not account for 1. (The values for these three flags are 0, 1, and 2, and for historical reasons, these three values are mutually exclusive-only one of these three values can be found in a file.) So first it is necessary to use the shielding character o_accmode and to obtain the access mode bit, and then compare the result with these three kinds of values.
F_SETFL set to the ARG descriptor status flag, several flags that can be changed are: O_append,o_nonblock,o_sync and O_async.
There are 7 file status flags in Fcntl: O_rdonly, O_wronly, O_rdwr, O_append, O_nonblock, O_sync and O_async
The following flags can be changed:
O_nonblock non-blocking I/O if the Read (2) call does not have readable data, or if the write (2) operation is blocked, the read or write call will return 1 and Eagain error
O_append force each write operation to be added at the end of the file, equivalent to the O_APPEND flag of open (2)
O_async allows the Sigio signal to be sent to the process group when I/O is available, for example: when there is data to read
Record locks are divided into read and write locks, where read locks, also known as shared locks, enable multiple
* Processes are able to establish read locks in the same part of the file. A write lock is also called a mutex,
* Only one process can have a write lock in one part of the file at any time. Of course, in
* Both read and write locks cannot be created in the same part of the file.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
Custom error handling functions
void My_err (const char * err_string, int line)
{
fprintf (stderr, "line:%d", line);
Perror (err_string);
Exit (1);
}
The setting of the lock or the release
int lock_set (int fd, struct flock * lock)
{
if (Fcntl (FD, F_SETLK, lock) = = 0) {/* executed successfully */
if (lock-> L_type ==f_rdlck) {
printf ("Set read lock, PID:%d\n", Getpid ());
}else if (lock, L_type ==f_wrlck) {
printf ("Set write lock, PID:%d \ n", Getpid ());
}else if (lock-l_type = = F_unlck) {
printf ("Release lock, PID:%d \ n", Getpid ());
}
}
else {/* Failed to execute, return -1*/
Perror ("Lock operation fail \ n");
return-1;
}
return 0;
}
Test lock, returns 0 only if the lock specified by the test find parameter lock can be set.
int lock_test (int fd, struct flock *lock)
{
if (Fcntl (FD, F_GETLK, lock) = = 0) {//execution succeeded
if (Lock->l_type = = F_unlck) {//test discovery can set the lock according to the parameter lock}
printf ("Lock can be set in FD \ n");
return 0;
}else {//incompatible lock exists, print out the process ID that sets the lock
if (lock-L_type ==f_rdlck) {
printf ("Can ' t set lock, read lock have set by:%d \ n", lock-and l_pid);
}else if (lock->l_type ==f_wrlck) {
printf ("Can ' t set lock, write lock have set by:%d \ n", lock->l_pid);
}
Return-2;
}
}else {
Perror ("Get Incompatible locks fail");
return-1;
}
}
int main ()
{
int FD;
int ret;
struct flock lock;
Char read_buf[32];
Open or create a folder
if (FD = open ("example_65", O_creat | O_trunc | O_rdwr, s_irwxu)) = =-1) {
My_err ("Open", __line__);
}
if (Write (FD, "Test lock", 10)!=10) {
My_err ("Test", __line__);
}
Initialize the lock structure
memset (&lock, 0, sizeof (struct flock));
Lock.l_start = Seek_set;
lock.l_whence = 0;
Lock.l_len = 0;
Set Read lock
Lock.l_type =f_rdlck;
if (Lock_test (fd, &lock) = = 0) {//test can use file lock
Lock.l_type =f_rdlck;
Lock_set (FD, &lock);
}
Read data
Lseek (FD, 0, Seek_set);
if (ret = read (FD, READ_BUF, ten)) < 0) {
My_err ("read", __line__);
}
Read_buf[ret] = = ' + ';
printf ("%s \ n", read_buf);
Wait for any key
GetChar ();
Set Write lock
Lock.l_type = F_wrlck;
if (Lock_test (fd, &lock) = = 0) {//test can set lock
Lock.l_type = F_wrlck;
Lock_set (FD, &lock);
}
Release lock
Lock.l_type = F_unlck;
Lock_set (FD, &lock);
Close (FD);
return 0;
}
Linux C Note file (ii)