Reprint please indicate source: http://blog.csdn.net/cywosp/article/details/30083015
1. Overview of the scenein the multi-threaded development, the mutex can be used to protect the critical resources and prevent inconsistent data, which is the most common use method. How do you handle synchronization between files in multiple processes? Let's take a look at the following figure: The figure shows the process of updating the same file at the same time without synchronizing the two processes, the main operation being:
1. Read the serial number from the file. 2. Use this sequence number to complete the application-defined tasks. 3. Increment the sequence number and write it back to the file.
It is known that two process reads have increased the number of reads, and write back to the file, but if there is mutual exclusion, the last value should be 1002 instead of the 1001 shown. To prevent this, Linux provides flock (for the entire file locking), Fcntl (locking for the entire file area) two functions for inter-process file synchronization. You can also use semaphores to accomplish the required synchronization, but it is usually better to use a file lock because the kernel can automatically associate locks with files.
2. Flock ()Flock's statement is as follows
#include <sys/file.h>
//Returns 0 on success, or-1 on Error int flock (int
fd,int
operation);
The fcntl () function provides a more powerful function than the function, and features that are also covered by flock (), but in some applications the flock () function is used, and in some semantics of inheritance and lock release flock () and fcntl () is still different. The flock () system call is to lock the entire file by manipulating the file pointed to by the incoming FD, and then determining what to do with the value set by the operation parameter. Operation can be assigned the following values: by default, if another process already holds an incompatible lock on the file, then flock () blocks. If you need to prevent this from occurring, you can take an OR (|) value in the operation parameter. In this case, if a process has already held an incompatible lock on the file, then flock () will block, instead it will return-1, and the errno will be set to Ewouldblock.
any number of processes can hold a shared lock on a file at the same time, but only one process can hold the mutex on a file at any one time (this is a bit like a read-write lock). is the support for process A to set the lock after the lock is set, and process B: regardless of the mode in which the program opens the file (read, write, or read/write), a shared or mutex can be placed on the file. During the actual operation, the parameter operation can specify the corresponding value to convert the shared lock into a mutex (and vice versa). Converting a shared lock to a mutex is blocked if another process is acquiring a shared lock on the file, unless the operation parameter specifies the LOCK_NB tag, which is: (Lock_sh | LOCK_NB). The conversion of a lock is not an atomic operation, and in the process of conversion, the lock is removed first, and then a new lock is created.
3. The semantics of lock inheritance and releaseflock () releases a file lock based on the value of the operation parameter passed in to the Lock_un at the time of invocation. Additionally, the lock is automatically freed after the corresponding file descriptor is closed. Also, when a file descriptor is copied (DUP (), dup2 (), or a fcntl () F_DUPFD operation), the new file description inode references the same file lock.
Flock (FD, LOCK_EX); new_fd = DUP (FD); Flock (NEW_FD, lock_un);
This code first sets a mutex on the FD, then creates a new file descriptor new_fd with the same file through FD, and finally unlocks by NEW_FD. So we can learn that the new file descriptor points to the same lock. Therefore, if a lock is acquired through a particular file descriptor and one or more copies of the descriptor are created, the lock will not be released until the file descriptor copy is closed, if an unlock operation is not displayed. from the above we can roll, if you use fork () to create a child process, the child process copies all the descriptors in the parent process, so that they also point to the same file lock. For example, the following code causes a child process to delete a lock on a parent process:
Flock (FD, LOCK_EX); If (0 = = Fork ()) { flock (FD, lock_un); }
Therefore, it is sometimes possible to use these semantics to transfer a file lock from the parent process to the child process: after the fork (), the parent process closes its file descriptor, and the lock is only under the control of the child process. Locks created by fork () are retained in exec () (unless the close-on-exec tag is set on the file descriptor and the file descriptor is the last descriptor that references the underlying open file description). If you use open () in your program to get a second descriptor that references the same file, flock () treats it as a different file descriptor. The following code will block on the second flock ().
fd1 = open ("Test.txt", O_RDWD); fd2 = open ("Test.txt", O_RDWD); Flock (FD1, lock_ex); Flock (FD2, lock_ex);
4. Limitations of flock ()flock () locks are placed with the following restrictions
- Only the entire file can be locked. This coarse-grained lock limits concurrency between collaboration processes. If there are multiple processes, each of these processes wants to access different parts of the same file at the same time.
- Only an advisory lock can be placed through flock ().
- Many NFS implementations do not recognize locks placed by flock ().
Note: File locks are advised by default, which means that a process can simply ignore the locks placed on the file by another process. To make the exhortation lock model work properly, all processes that access the file must be matched by placing a lock before the file IO is executed.