文件锁
Posted it8343
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件锁相关的知识,希望对你有一定的参考价值。
当多个进程都需要对同一个文件进行读写操作的时候,有时候需要确保进程在一次读写操作完 成之前,文件不被其他进程修改。文件锁机制提供了这样的同步功能。 int fcntl(int fd, int cmd, struct flock *lock); fcntl()函数操作文件锁时 cmd 是 F_GETLK、F_SETLK 和 F_SETLKW。第三个参数是指向 struct flock 的指针,flock 结构体包含了下面的成员: struct flock
{ short l_type; /* 锁的类型 */ short l_whence; /* 加锁的文件区域起点偏移的基准点*/ off_t l_start; /* 加锁的文件区域起点相对l_where偏移量 */ off_t l_len; /* 加锁的文件区域长度是多少字节 */ pid_t l_pid; /* F_GETLK返回的已经对文件加锁的进程ID */ }; 文件锁有互种类型,由 flock 结构中的 l_type 指定: F_RDLCK:读锁 F_WRLCK:写锁 F_UNLCK:解锁 锁定文件的区域起点是由 l_whence 和 l_start 共同决定的,l_whence 为些准点,可以 取 SEEK_SET,SEEK_CUR,SEEK_END 中的一个,l_start 是相对基准点的偏移量。这样介绍文 件偏移的 lseek()函数的参数是一样的。 锁定文件的区域的长度由 l_len 指定,如果 l_en 为 0,表示锁定从起点开始到文件尾 的区域。 为了锁定整个文件,通常的方法是将 l_start 指定为 0,l_whence 指定为 SEEK_SET, l_len 指定为 0。
下面来说明一下三个 cmd 参数的作用和用法: F_GETLK:查看文件描述符 fd 指向的文件中,由参数 lock 描述的锁是否被另外一把锁拒绝。按照表中的兼容性规则,如果 lock描述的锁被拒绝,那么把这把锁的信息写入参数
lock指向的结构体中。如果 lock 可以被加入,lock 参数中的 l_type 被设置为 F_UNLCK。 F_SETLK:设置参数 lock 描述的锁,如果按表的兼容性规则被拒绝加锁,则 fcntl()函数立即出错返回。此时 errno 为 EACCESS 或者 EAGAIN。 F_SETLKW:这是 F_SETLK 的阻塞版本,如果新加的锁被拒绝,那么进程被阻塞直到可以加锁。
1 #include"common.h" 2 3 /*使用 fcntl()函数来进行文件锁操作的时候,每次都要 4 声明一个结构体并赋值,代码看上之很不整洁,因此先封装一些函数:*/ 5 int set_lock( int fd, int cmd, int type, off_t offset, int whence, off_t 6 len ) 7 { 8 struct flock lock; 9 lock.l_type = type; 10 lock.l_start = offset; 11 lock.l_whence = whence; 12 lock.l_len = len; 13 return ( fcntl( fd, cmd, &lock ) ); 14 } 15 16 //利用宏定义: 17 18 /* 加一把读锁 */ 19 #define read_lock( fd, offset, whence, len ) 20 set_lock( fd, F_SETLK, F_RDLCK, offset, whence, len ) 21 /* 用阻塞方式加一把读锁 */ 22 #define readw_lock( fd, offset, whence, len ) 23 set_lock( fd, F_SETLKW, F_RDLCK, offset, whence, len ) 24 /* 加一把写锁 */ 25 #define write_lock( fd, offset, whence, len ) 26 set_lock( fd, F_SETLK, F_WRLCK, offset, whence, len ) 27 /* 用阻塞方式加一把写锁 */ 28 #define writew_lock( fd, offset, whence, len ) 29 set_lock( fd, F_SETLKW, F_WRLCK, offset, whence, len ) 30 /* 解锁 */ 31 #define un_lock( fd, offset, whence, len ) 32 set_lock( fd, F_SETLK, F_UNLCK, offset, whence, len ) 33 34 35 /*用这五个函数,可以方便的对某个文件区域进行加锁和解锁*/ 36 37 38 /*测试一把锁的函数*/ 39 pid_t test_lock(int fd, int type, off_t offset, int whence, off_t len ) 40 { 41 struct flock lock; 42 lock.l_type = type; 43 lock.l_start = offset; 44 lock.l_whence = whence; 45 lock.l_len = len; 46 if( fcntl( fd, F_GETLK, &lock ) == -1 ){ 47 perror( "fcntl" ); 48 return -1; 49 } 50 if( lock.l_type == F_UNLCK ){ 51 return 0; 52 } 53 return lock.l_pid; 54 } 55 /*打印函数*/ 56 void pid_printf( char *format, ... ) 57 { 58 va_list ap;/*va在这里是variable-argument(可变参数)的意思*/ 59 va_start( ap, format ); 60 printf("[%d]:", getpid() ); 61 vprintf( format, ap ); 62 va_end(ap); 63 } 64 65 int main( int argc, char **argv ) 66 { 67 int fd; 68 pid_t pid; 69 pid_t lpid; 70 /*创建一个文件*/ 71 fd = creat( "./file1", 0640 );//(0640文件属性) 72 if( fd == -1 ) 73 { 74 perror( "create file1 error!" ); 75 } 76 pid_printf("./file1 created, fd = [%d] ", fd); 77 /*给文件加写锁*/ 78 pid_printf("lock file now "); 79 write_lock( fd, 0, SEEK_SET, 0 );//锁定整个文件(写) 80 /*派生进程*/ 81 pid = fork(); 82 if( pid == 0 ) 83 { 84 /*子进程打开文件*/ 85 fd = open( "./file1", O_RDWR ); 86 if( fd == -1 ) 87 { 88 perror( "open file1 error!" ); 89 } 90 /*一直等到文件解锁*/ 91 while( 1 ) 92 { 93 lpid = test_lock( fd, F_RDLCK, 0, SEEK_SET, 0 ); 94 if( lpid > 0 ) 95 { 96 pid_printf("process [%d] locked file1 ",lpid ); 97 }else if( lpid == 0 ) 98 { 99 pid_printf("file1 unlocked "); 100 break; 101 } 102 else 103 { 104 break; 105 } 106 sleep(1); 107 } 108 close( fd ); 109 } 110 else if( pid != -1 ) 111 { 112 sleep(3); 113 pid_printf("Unlock write lock of file1 now "); 114 /*给文件解锁*/ 115 un_lock( fd, 0, SEEK_SET, 0 ); 116 /*等待子进程退出*/ 117 waitpid(pid,NULL,0); 118 }else 119 { 120 printf("There was an error with forking! "); 121 } 122 close( fd ); 123 return 0; 124 } 125
运行结果:
[22792]:./file1 created, fd = [3] [22792]:lock file now [22793]:process [22792] locked file1 [22793]:process [22792] locked file1 [22793]:process [22792] locked file1 [22792]:Unlock write lock of file1 now [22793]:file1 unlocked
以上是关于文件锁的主要内容,如果未能解决你的问题,请参考以下文章