http://blog.csdn.net/ly21st http://ly21st.blog.chinaunix.net
分类: LINUX
2011-09-16 14:35:53
有两种基本的文件上锁形式,它们是
1)文件上锁;
2)上锁的区域。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7
8 void lock_file(void)
9 {
10 int fd = -1;
11 do{
12 fd = open("file.lck",O_WRONLY|O_CREAT|O_EXCL,0666);
13 if ( fd==-1 ) {
14 if ( errno == EEXIST )
15 sleep(1);
16 else {
17 fprintf(stderr,"%s:create lock file file.lck\n",strerror(errno));
18 abort();
19 }
20 }
21 }while(fd==-1);
22 close(fd);
23 }
24
25 void unlock_file(void)
26 {
27 unlink("file.lck");
28 }
29
30 int main(int argc, char **argv)
31 {
32 FILE *fp;
33 char ch;
34 int lock=1;
35 int i;
36
37 if (argc >=2 && strcasecmp(argv[1],"nolock") )
38 lock = 0;
39 for (i=0; i<1000; i++)
40 {
41 if (lock)
42 lock_file();
43 fp=fopen("file.dat","r+");
44 if (fp ==NULL && errno ==ENOENT )
45 fp=fopen("file.dat","w");
46 if (!fp){
47 printf("open file.dat error\n");
48 if (lock)
49 unlock_file();
50 return 1;
51 }
52 fseek(fp,0,SEEK_END);
53 fprintf(fp,"%05ld i=%d ",(long)getpid(),i);
54 for(ch=' '; ch < 'z'; ch++)
55 {
56 fputc(ch,fp);
57 sleep(0.000005);
58 }
59 fputc('\n',fp);
60 fclose(fp);
61
62 if (lock)
63 unlock_file();
64 }
65 printf("process %ld completed\n",(long)getpid());
66 return 0;
67 }
但是,上面上锁文件的一些缺点是:
1)当使用sleep()时,两次失败的试图之间有很长的反应时间;
2)在NFS文件系统上使用时,它不可靠;
3)它是粗粒度上锁(这意味着进程上锁整个文件);
因此要考虑其他文件上锁的方法。
使用flock()上锁
int flock(int fd, int operation);
#define LOCK_SH 0x01 //shared file lock
#define LOCK_EX 0x02 //exclusive file lock
#define LOCK_NB 0x04 // don’t block when locking
#define LOCK_UN 0x08 // unlock file
flock()函数具有一些优点超过上锁文件技术:
1)不包含附加的上锁条件;
2)重新上锁时,不调用sleep(),提供了改进的性能;
3)更细粒度的上锁允许上锁共享或独占;
4)容许上锁控制在NFS安装文件系统上
记录上锁:
int lockf(int fd, int request, off_t size);
该函数是要被Posix fcntl()接口放弃的,不再对它进行详细说明。
使用fcntl()上锁
#include
#include
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
F_GETFL
Read the file status flags.
F_SETFL
Set the file status flags to the value specified by arg. File access mode (O_RDONLY,
O_WRONLY, O_RDWR) and file creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in
arg are ignored. On Linux this command can only change the O_APPEND, O_ASYNC,
O_DIRECT, O_NOATIME, and O_NONBLOCK flags.
Advisory locking
F_GETLK, F_SETLK and F_SETLKW are used to acquire, release, and test for the existence of
record locks (also known as file-segment or file-region locks). The third argument lock is a
pointer to a structure that has at least the following fields (in unspecified order).
struct flock {
...
short l_type; /* Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock
(F_GETLK only) */
...
};
Mandatory locking
(Non-POSIX.) The above record locks may be either advisory or mandatory, and are advisory by
default.
Advisory locks are not enforced and are useful only between cooperating processes.
Mandatory locks are enforced for all processes. If a process tries to perform an incompatible
access (e.g., read(2) or write(2)) on a file region that has an incompatible mandatory lock,
then the result depends upon whether the O_NONBLOCK flag is enabled for its open file descrip-
tion. If the O_NONBLOCK flag is not enabled, then system call is blocked until the lock is
removed or converted to a mode that is compatible with the access. If the O_NONBLOCK flag is enabled, then the system call fails with the error EAGAIN or EWOULDBLOCK.
To make use of mandatory locks, mandatory locking must be enabled both on the file system that
contains the file to be locked, and on the file itself. Mandatory locking is enabled on a file system using the "-o mand" option to mount(8), or the MS_MANDLOCK flag for mount(2).Mandatory locking is enabled on a file by disabling group execute permission on the file and enabling the set-group-ID permission bit (see chmod(1) and chmod(2)).