(1) Fcntl function description
The previous 5 basic functions enable the opening of the file, read and write basic operations, this section will discuss how the file has been shared in the case of how to operate, that is, when more than one user to work together to manipulate a file, at this time, Linux is usually used in the way to lock the file, To avoid the competing state of shared resources.
File locks include recommended locks and mandatory locks.
The recommended lock requires each lock file process to check for latches and respect for existing locks. In general, the kernel and the system do not use a recommended lock. A mandatory lock is a lock that is executed by the kernel, and when a file is locked for writing, the kernel blocks any other file from reading or writing to it. The use of mandatory locks has a significant effect on performance, and every read and write operation must check whether there is a lock.
In Linux, the function to lock files is lock and fcntl, in which flock is used to impose a recommended lock on the file, and fcntl can not only apply the recommended lock, but also can strengthen the lock. At the same time, Fcntl can also lock a record of a file, that is, record the lock.
Record locks can be divided into read locks and write locks, where read locks are also known as shared locks, which enable multiple processes to establish read locks in the same part of the file. Write locks are also known as exclusion locks, and only one process can create write locks on one part of a file at any given time. Of course, both read and write locks cannot be established in the same part of the file.
Fcntl is a very common function that can also change the properties of various aspects of the file process, in this section, the main way to establish a record lock, readers interested in other users can refer to the FCNTL manual.
(2) FCNTL function format
The FCNTL function format used to establish a record lock is shown in table 6.6.
Table 6.6 fcntl function Syntax Essentials required header File
Copy Code code as follows:
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
function prototype int fcnt1 (int fd, int cmd, struct flock *lock)
F_DUPFD: Copy file descriptor
F_GETFD: Get the CLOSE-ON-EXEC flag of FD, if the flag is not set, the file will remain open after the EXEC function
F_SETFD: Sets the CLOSE-ON-EXEC flag, which is determined by the fd_cloexec bit of the parameter arg
F_GETFL: Flags to get open settings
F_SETFL: Change the flag of the open setting
F_GETFK: Depending on the lock description, decide whether to lock the file
F_SETFK: Set lock description of the file
F_SETLKW: This is the blocked version of the F_SETLK (the W in the command name indicates waiting (wait)).
Call Process sleep If there are other locks, or sleep breaks if a signal is caught
F_getown: Retrieves the process number or process group number that will receive Sigio and Sigurg signals
F_setown: Set process number or process group number
Lock: The structure is flock, setting the specific state of the record lock, which will be described in detail later
Here, the structure of the lock is shown below:
Copy Code code as follows:
Struct flock{
Short L_type;
off_t L_start;
Short l_whence;
off_t L_len;
pid_t L_pid;
}
The value meaning of each variable in the lock structure is shown in table 6.7.
Table 6.7 Lock struct Variable value
F_rdlck: Read lock (Shared lock)
L_type F_wrlck: Write lock (excluding lock)
F_unlck: Unlock
L_stat relative Displacement (bytes)
Seek_set: The current position is the beginning of the file, the new position is the size of the offset
Seek_cur: The current position is the position of the file pointer, the new position is the current position plus the offset
L_whence: The starting point of relative displacement (whence with lseek).
Seek_end: The current position is the end of the file, and the new location is the size of the file plus the offset size
L_len the length of the lock area
To lock the entire file, the usual method is to 0,l_whence the L_start description to the Seek_set,l_len description as 0.
The following first gives a file record lock function using the FCNTL function. In this function, the corresponding bit of the flock structure body is first given a value. Then use two times Fcntl function respectively to lock the relevant files and determine whether the file can be locked, the use of the CMD value is f_setlk and F_GETLK respectively.
The source code for this function is as follows:
Copy Code code as follows:
/*lock_set function * *
void Lock_set (int fd, int type)
{
struct flock lock;
Lock.l_whence = seek_set;//Assignment Lock structure body
Lock.l_start = 0;
Lock.l_len = 0;
while (1) {
Lock.l_type = type;
/* Lock or unlock files according to different type values.
if ((Fcntl (FD, F_SETLK, &lock)) = = 0) {
if (Lock.l_type = = F_rdlck)
printf ("read lock set by%d\n", Getpid ());
else if (Lock.l_type = = F_wrlck)
printf ("Write lock set by%d\n", Getpid ());
else if (Lock.l_type = = F_unlck)
printf ("Release lock by%d\n", Getpid ());
Return
}
* To determine whether the file can be locked/*
Fcntl (FD, F_getlk,&lock);
* * To determine the reasons for the document can not be locked
if (Lock.l_type!= f_unlck) {
/*/the file has a write lock * *
if (Lock.l_type = = F_rdlck)
printf ("read lock already set by%d\n", lock.l_pid);
* * The file has read lock/
else if (Lock.l_type = = F_wrlck)
printf ("Write lock already set by%d\n", lock.l_pid);
GetChar ();
}
}
}
The following example is a write lock for a test file, where a hello file is first created, a lock is written on it, and the write lock is finally released. The code looks like this:
Copy Code code as follows:
/*FCNTL_WRITE.C test File Write lock main function part * *
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int FD;
/* First Open the file * *
Fd=open ("Hello", O_RDWR | O_creat, 0666);
if (FD < 0) {
Perror ("open");
Exit (1);
}
/* Write a lock to the file/*
Lock_set (FD, F_WRLCK);
GetChar ();
/* To file the lock * *
Lock_set (FD, F_UNLCK);
GetChar ();
Close (FD);
Exit (0);
}
In order to be able to use a number of terminals to better display the role of write locks, this example is mainly tested on the PC, the reader can cross compile, download to the target board to run. The following are the results of the operation on the PC. In order to make the program have a greater flexibility, the author uses the file locked by the user type a key to enable the program to continue to run. It is recommended that readers turn on two terminals and run the program simultaneously on two terminals to achieve the effect of multiple processes manipulating a file. Here, I first run terminal one, please pay attention to the first sentence in terminal two.
Terminal One:
Copy Code code as follows:
[Root@localhost file]#./fcntl_write
Write lock set by 4994
Release lock by 4994
Terminal two:
Copy Code code as follows:
[Root@localhost file]#./fcntl_write
Write lock already set by 4994
Write lock set by 4997
Release lock by 4997
Thus, the write lock is a mutex, and only one write lock exists at a time.
The next program is the test file read lock, the principle of the same as the above program.
Copy Code code as follows:
/*FCNTL_READ.C test File read lock main function part * *
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int FD;
Fd=open ("Hello", O_RDWR | O_creat, 0666);
if (FD < 0) {
Perror ("open");
Exit (1);
}
* * To read the lock on the file * *
Lock_set (FD, F_RDLCK);
GetChar ();
/* To file the lock * *
Lock_set (FD, F_UNLCK);
GetChar ();
Close (FD);
Exit (0);
}
Also open two terminals, and first start the program on the terminal One, the results of the operation are as follows:
Terminal One:
Copy Code code as follows:
[Root@localhost file]#./fcntl2
Read lock set by 5009
Release lock by 5009
Terminal two:
Copy Code code as follows:
[Root@localhost file]#./fcntl2
Read lock set by 5010
Release lock by 5010
Readers can compare this result with the result of the write lock, which shows that the read lock is a shared lock, and process 5010 can also set read locks after the process 5009 has been set to read the lock.
thinking:
If you run the set read lock on one terminal, then run the set write lock on the other terminal, what will be the result?