Linux file (Zone) lock function--open (), FCTNL ()

Source: Internet
Author: User
Tags flock

One, what is file lock

For the word lock, we must not be unfamiliar, because we live in a large number of locks, they play its role in all aspects of the world, now the function of the lock can be summed up as a sentence, is to prevent some people do something, for example, the door lock is to prevent people other than the owner into this House, you can not enter the house , you can't use anything inside the house.

And because programs often need to share data, and this is usually done through files, imagine a situation where a process is writing a file, while another program B needs to read the same file and read the data as it needs to run its own program, what happens? Process B may read the data in the confusion because it does not know that another process A is overwriting the data in the file.

In order to solve similar problems, there is a file lock, simple point, this is a safe way to update the file, when a program is writing to the file, the file will enter a temporary state, in this state, if another program tries to read the file, it will automatically stop waiting for this state to end. Linux systems provide many features for file locking, the simplest of which is to create lock files in an atomic operation.

The previous example is that the file lock is when the file is written, blocking other processes that need to be written or read to manipulate the file.

Ii. Creating a lock file

Creating a lock file is very simple, we can use open system call to create a lock file, oflags parameter to add parameters O_creat and O_EXCL flag when open is called, such as File_desc = Open ("/tmp/lck.test", O_ rdwr| O_creat| O_EXCL, 0444); You can create a lock file/tmp/lck.test. O_creat| O_EXCL, can ensure that the caller can create a file, using this mode can prevent two programs to create the same file at the same time, if the file (/tmp/lck.test) already exists, the open call will fail, return-1.

If a program executes, it only needs to monopolize a resource for a short time, this time period (or code area) is often called the critical section, we need to create a lock file using the open system call before entering the critical section, and then delete the lock file with the unlink system call when exiting the critical section.

Note: Lock files are just roles that act as an indicator, and programs need to work together to use them, which means that lock files are only recommended locks, not forced locks, and do not really prevent you from reading and writing data in a file.

Take a look at the following example: The source file is named filelock1.c and the code is as follows:

#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include < Errno.h>int Main () {const char *lock_file = "/tmp/lck.test1"; int n_fd = -1;int n_tries = 10;while (n_tries--) {//Create lock file N_ FD = open (Lock_file, O_RDWR | O_creat | O_EXCL, 0444); if (n_fd = =-1) {//Create failed printf ("%d-lock already present\n", getpid ()); Sleep (2);} else{//created successfully printf ("%d-i has exclusive access\n", Getpid ()); sleep (1); close (N_FD);//delete lock file, Release lock unlink (lock_file); Sleep (2);}} return 0;}

Running two instances of the same program at the same time, the result is:

From the running results can be seen two programs cross-lock the file, but the real operation is, each call to the Open function to check the/tmp/ Lck.test1 This file exists, if there is an open call fails, it shows that the process has locked the file, if the file does not exist, create the file and display the license information. However, this approach has some shortcomings, we can see that the file/tmp/lck.test1 has been created many times, also by unlink deleted many times, that is, we can not use the file has been pre-existing data as such a lock file, because if the file already exists, the open call will always fail.

The feeling is that this is more like a coordination arrangement for the work of the process, more like the role of binary semaphore, the file exists as 0, there is no 1, not the real file lock.

Three, Zone lock

We also have a problem, that is, if the same file has more than one process to read it, and a file can only be written by one process at the same time, but multiple processes read and write the region is not related, if it is always necessary to wait for a process to write other processes to read and write, the efficiency is too low, So is it possible for multiple processes to read and write files at the same time to improve the efficiency of data read and write?

In order to solve the problem mentioned above, and the problem appearing in the 2nd, that is, we cannot lock the file to the specified existing data file, we propose a new solution, that is, Zone locking.

In simple terms, a zone lock is a part of a file that is locked, but other programs can access other parts of the file.

However, the creation and use of zone locks is much more complex than the file locks described above.

1. Create a zone lock

For this to work on Linux, we can use FCNTL system calls and LOCKF calls, but the following is a fcntl system call to explain the creation of a zone lock.

The function prototypes for FCTNL are:

int fctnl(int fildes, int command, struct flock *flock_st);

It operates on an open file description and can perform different tasks according to the command parameter settings, which has three optional tasks: f_getlk,f_setlk,f_setlkw, the meaning of these three parameters is described in detail below. When you use these commands, the third argument of fcntl must be a pointer to the flock structure.

2. Flock Structure

To be precise, the flock structure relies on a specific implementation, but it includes at least the following members:

Short l_type: The type of the file lock, which corresponds to F_rdlck (read lock, also called shared lock), F_unlck (unlocked, also called clear Lock), F_wrlck (write lock, also called exclusive lock).

Short l_whence: calculates from which relative position of the file, corresponds to Seek_set (file header), Seek_cur (current position), one of Seek_end (end of file).

off_t L_start: Starts at L_start bytes beginning with l_whence.

off_t L_len: The length of the locked area.

pid_t l_pid: The process used to record the lock that the parameter holds.

Members L_whence, L_start, and L_len define a region in a file, a contiguous set of bytes, for example:

struct flock region;region.l_whence = Seek_set;region.l_start = 10;region.l_len = 20;

The Fcntl function operation locks the 20 bytes between the 10th to 29th byte of the beginning of the file header.

3. Type of File lock

From the above Flock member L_type of the value we can know, there are three types of file locks, they are explained in detail here.

F_rdlck:

From its name we can know that it is a read lock, also called a shared lock. Many different processes can have read (shared) locks on the same (or overlapping) area of the file. And as long as either process has a read (shared) lock, no process can obtain a write (exclusive) lock on that region. In order to obtain a shared lock, the file must be opened in "read" or "read/write" mode.

Simply put, when a process is reading the data in the file, the data in the file cannot be changed or rewritten, it is easy to understand that the same area of the file can be read by multiple processes at the same time in order to prevent the data from being changed and to read the data to the garbled data, which is understandable because reading does not destroy the data. Or the read operation does not alter the file's data.

F_wrlck:

From its name, we can know that it is a write lock, also called an exclusive lock. Only one process can have a write (exclusive) lock in any particular area of the file. Once a process has such a lock, no other process can acquire any type of lock on that area. In order to obtain a write (exclusive) lock, the file must also be opened in "read" or "read/write" mode.

Simply put, it is a file with the same region (or overlapping) region at the same time, only one process can write to it, and during the write operation, other processes cannot read the data to the zone. This requirement is obviously easy to see because if two processes write to a file at the same time, the contents of the file will be garbled, and the data in the file will be changed in writing, so it does not allow other processes to read and delete files.

F_unlck:

It can be known from its name and is used to unlock a locked area.

4. The meaning of different command

Speaking of the command parameters of the FCNTL function, we said three options, which will be explained in detail here.

The F_GETLK command, which is used to get the lock information for a file opened by Fildes (the first parameter of Fcntl), does not attempt to lock the file, the calling process can pass the lock type information it wants to create to fcntl, and the function call returns any information that will block the acquisition of the lock. That is, it can test whether the lock you want to create can be successfully created. When the FCNTL call succeeds, it returns non-1, and if the lock request can be executed successfully, the flock structure remains unchanged, and if the lock request is blocked, fcntl overwrites the flock structure with the relevant information. Returns-1 on failure.

So, if the call succeeds, the calling program can check the contents of the flock structure to see if it has been modified, to check if the lock request is executed successfully, and because the value of L_pid is set to the identifier of the process that owns the lock, so in most cases You can determine whether the flock structure has been modified by checking whether the field has changed.

The FCNTL function call that uses F_GETLK returns immediately.

For example, for instance, there is a flock structure variable, flock_st,flock_st.l_pid =-1, the 10th to 29th byte of the file already has a read lock, a write lock already exists in the 40th to 49th byte of the file, and when Fcntl is called, the F_ The GETLK command, to test whether a read lock can be created in the 10th to 29th Byte, because the lock can be created, so fcntl returns non-1, and the contents of the flock structure do not change, Flock_st.l_pid =-1. And if we test whether a write lock can be created in the 40th to 49th byte, the test fails because there is already a write lock in the zone, but Fcntl still returns non-1, except that the flock structure is overwritten with information about the lock associated with the zone, Flock_st.l_ The PID is the process identifier for the process that owns the write lock.

The F_SETLK command, which attempts to lock or unlock an area of a file that Fildes points to, depends on the l_type value of the flock structure. For this command, the L_pid field of the flock structure is meaningless. If the lock succeeds, returns non-1, or 1 if it fails. The FCNTL function call that uses F_SETLK returns immediately.

The F_SETLKW command, which works the same as the previous F_SETLK command, but differs in that it waits until it can be locked when the lock cannot be acquired, that is, the test cannot be locked.

5. Example

Having read so many instructions, you may have been in a mess, just use the following example to clear your mind.

The source file is named filelock2.c, which is used to create the data file and lock the file area with the following code:

#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main (int argc, Char **argv) {const char *test_file = "./test_lock.txt"; int file_desc = -1;int Byte_count = 0;char *byte_to_write = "A"; str UCT Flock region_1;struct flock region_2;int res = 0;//Open a file m descriptor File_desc = open (Test_file, o_rdwr| O_creat, 0666), if (!file_desc) {fprintf (stderr, "Unable to open%s for read/write\n", test_file); exit (exit_failure);} Add 100 ' a ' characters to the file for (byte_count = 0; Byte_count < ++byte_count) {write (File_desc, byte_to_write, 1);} Set read lock on 10th to 29th byte of file (Shared lock) Region_1.l_type = F_rdlck;region_1.l_whence = Seek_set;region_1.l_start = 10;region_1.l_len = 2 0;//Set Write lock (exclusive lock) in 40~49 byte of file Region_2.l_type = F_wrlck;region_2.l_whence = Seek_set;region_2.l_start = 40;region_2.l_len = 10;printf ("Process%d locking file\n", getpid ());//Lock file res = Fcntl (File_desc, F_setlk, region_1); if (res = =-1) {fprintf (s Tderr, "Failed to lock Region 1\n");} res = Fcntl (File_desc, F_setlK, region_2); if (res = =-1) {fprintf (stderr, "Failed to lock Regin 2\n");} Let the program sleep for 1 minutes to test sleep;p rintf ("Process%d closing file\n", Getpid ()); close (File_desc); exit (exit_success);}

The following source file filelock3.c is used to test the lock on the previous file setting, and the test can add a read lock to all two zones, with the following code:

#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main (int argc,  Char **argv) {const char *test_file = "./test_lock.txt"; int file_desc = -1;int res = 0;//Open Data File File_desc = open (Test_file, o_rdwr| O_creat, 0666), if (!file_desc) {fprintf (stderr, "Unable to open%s for Read/write", test_file); exit (exit_failure);} Set lock type for zone 1 struct flock Region_test1;region_test1.l_type = F_rdlck;region_test1.l_whence = Seek_set;region_test1.l_ Start = 10;region_test1.l_len = 20;region_test1.l_pid = -1;//Set Lock type for Zone 2 struct flock Region_test2;region_test2.l_type = F_ Rdlck;region_test2.l_whence = Seek_set;region_test2.l_start = 40;region_test2.l_len = 10;region_test2.l_pid = -1;// Whether the Zone 1 can be added with a read lock to test res = FCNTL (File_desc, F_getlk, region_test1); if (res = =-1) {fprintf (stderr, "Failed to get Rdlck\n");} if (region_test1.l_pid = =-1) {//Can be added with a read lock printf ("Test:process%d could lock\n", getpid ());} else{//is not allowed to add a read lock printf ("Test:process%d get lock failure\n", Getpid ());} // If the Q area 2 can be added a read lock to test res = FCNTL (File_desc, F_getlk, region_test2); if (res = =-1) {fprintf (stderr, "Failed to get Rdlck\n");} if (region_test2.l_pid = =-1) {//Can be added with a read lock printf ("Test:process%d could lock\n", getpid ());} else{//is not allowed to add a lock printf ("Test:process%d get lock failure\n", Getpid ());} Exit (exit_success);}

The results of the operation are as follows:

Because a read lock exists in zone 1, it is possible to add a read lock on top of it, but the lock on Zone 2 is a write lock and cannot be added to any type of lock, so the test fails. Note that the test failure is not a FCTNL call failure, it returns non-1, and we determine the test result by checking the members of the flock structure l_pid.

third, solve the problem of empty lock

What happens if I'm going to unlock an area that's not locked in this process? And what happens if other processes in the region lock it up?

If a process does not actually lock a zone, the call unlock operation succeeds, but it does not solve the lock that other processes add to the same region. It can also be said that the final result of an unlock request depends on any locks that the process has set in the file, without locking, but unlocked by unlocking it.

Reference:

http://blog.csdn.net/ljianhui/article/details/10075795

Linux file (Zone) lock function--open (), FCTNL ()

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.