目录
高级文件操作-文件锁
- 当多个用户共同使用、操作一个文件的时候,linux通常采用的方法是给文件上锁,来避免共享资源产生竞争的状态。
文件锁按功能分为
共享读锁
- 文件描述符必须读打开
- 一个进程上了读锁,其它进程也可以上读锁进行读取
独占写锁
- 文件描述符必须写打开
- 一个进程上了写锁,其它进程就不能上写锁和读锁进行读写操作
- 文件锁按类型分为建议性锁和强制性锁。
- 建议性锁要求上锁文件的进程都要检测是否有锁存在,并尊重已有的锁。
- 强制性锁由内核和系统执行的锁。
- fcntl不仅可以实施建议性锁而且可以实施强制性锁。
fcntl函数
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, struct flock *lock); cmd: F_SETLK、F_GETLK 和 F_SETLKW
flock结构体
l_type
- 锁类型,F_RDLCK(共享读锁)、F_WRLCK(独占性写锁)或F_UNLCK(解锁一个区域)
l_start、l_whence
- 要加锁或解锁的区域的起始地址,由l_start和l_whence 两者决定
- l_start是相对位移量,l_whence则决定相对位移量的起点。
l_len
- 表示区域的长度
加锁和解锁区域的注意
- 该区域可以在当前文件尾端处开始或越过其尾端处开始,但是不能在文件起始位置之前开始或越过该起始位置。
- 如若l_len为0,则表示锁的区域从其起点(由l_start和l_whence决定)开始直至最大可能位置为止。
- 也就是不管添写到该文件中多少数据,它都处于锁的范围。
- 为了锁整个文件,通常的方法是将l_start设为0,l_whence设为SEEK_SET,l_len设为0。
锁的继承与释放
- 一个进程终止,它所建立的锁全部释放
- 关闭一个文件描述符,此进程对应该文件的所有的锁均释放。
- 子进程不继承父进程的锁
- 执行exec以后,新程序可以选择是否继承原来执行进程的锁。
案例一
- io.h
#ifndef _IO_H_ #define _IO_H_ #include <sys/types.h> //... extern int lock_reg(int fd, int cmd, short type , off_t offset, short whence, off_t length); #define READ_LOCKW(fd, offset, whence, length) \ lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, length) #define READ_LOCK(fd, offset, whence, length) \ lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, length) #define WRITE_LOCKW(fd, offset, whence, length) \ lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, length) #define WRITE_LOCK(fd, offset, whence, length) \ lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, length) #define UNLOCK(fd, offset, whence, length) \ lock_ reg(fd, F_SETLK, F_UNLCK, offset, whence, length) #endif
- io.c部分代码
//... int lock_reg(int fd, int cmd, short type, off_t offset, short whence, off_t length) { struct flock flock; flock.l type = type; flock.l_start = offset; flock.l_whence = whence; flock.l_len = length; //flock.t_pid = getpid(); //l_pid:加锁、解锁进程的进程号(pid) if(fcntl(fd, cmd, &flock)< 0){ perror("fcntl error"); return 0; } return 1; )
- 编译
gcc -o obj/io.o -Iinclude -c src/io.c
- 调用
int main(int argc,char* argv[]){ if(argc < 4){ printf("usage:%S content file locktype\n", argv[0]); exit(1); } ssize_t size = strlen(argv[1]) * sizeof(char); int fd = open(argv[2],0_WRONLY | 0_CREAT,0777); if(fd < 0){ perror("open error"); exit(1); } //第二个进程想要对文件加文件锁(这里是独占写锁) //必须要等前一个进程释放了文件锁后方可加锁. if(!strcmp("lock", argv[3])) WRITE_LOCKW(fd, 0, SEEK_SET, 0); printf("lock success\n"); printf("lock pid:%d\n", getpid()); sleep(5); if(!strcmp("lock", argv[3])) WRITE_LOCKW(fd, 0, SEEK_SET, 0); printf("lock success\n"); printf("lock pid: %d\n", getpid()); char *p = argv[1]; int i; for(i = 0; i < size; i++){ if (write(fd, (p+i), 1)!= 1){ perror("write error"); exit(1); } printf("%d success write one character\n", getpid()); sleep(1); } if(!strcmp("unlock", argv[3])) UNLOCK(fd, 0, SEEK_SET, 0); printf ("unlock success\n"); printf("unlock pid: %d\n", getpid()); close(fd); return 0; }
- 编译
gcc -o bin/lock_write -Iinclude obj/io.o src/lock_write.c
- 编写start.h脚本文件
bin/lock_write aaaaaa demo.txt Lock & bin/Lock_write AAAAAA demo.txt lock &
- 运行结果
- 改变脚本如下
bin/lock_write aaaaaa demo.txt Lock & bin/Lock_write AAAAAA demo.txt unlock &
- 运行结果(第二个进程关闭了文件锁,没有锁时,由于这里的文件锁是建议性锁,所以能继续向文件中输入数据,出现交替输入的情况)
案例二
int main(int argc, char *argv[]){ if(argc < 4){ printf("usage: %S content file lock I unlock\n" , argv[0]); exit(1); } ssize_ t size = strlen(argv[1]) * sizeof(char); int fd = open(argv[2], 0_ WRONLY| 0_CREAT, 0777); if(fd < 0){ perror("open error"); exit(1) ; } char *p = argv[1]; int i; for(i = 0; i < size; i++){ if (write(fd, (p+i), 1) != 1){ perror("write error"); exit(1); } printf("%d success write one character\n", getpid()); sleep(1); } sleep(5); printf("current pid:%d\n", getpid()); if(!strcmp("'lock", argv[3])){ //加文件锁(这里是独占写锁) //第二个进程想要对文件加锁必须要等到 //第一个进程释放文件锁后方可枷锁. WRITE_LOCKW(fd, 0, SEEK_SET, 0); printf("lock success\n"); } if(!strcmp("lock", argv[3])){ UNLOCK(fd, 0, SEEK_SET, 0); printf("unlock success\n"); printf("unlock pid:%d\n", getpid()); } close(fd); return 0; }
- 编写start.h脚本文件
bin/lock_write aaaaaa demo.txt Lock & bin/Lock_write AAAAAA demo.txt lock &
- 改变脚本如下(由于这里的文件锁是建议性锁,不加锁也能向文件中写入数据)
bin/lock_write aaaaaa demo.txt Lock & bin/Lock_write AAAAAA demo.txt unlock &
Linux程序设计:高级文件操作-文件锁
最新推荐文章于 2021-08-30 19:11:01 发布