linux文件锁是默认的劝告锁。
以下证实两点:
1)读写锁分别的排他性。
2)当文件上锁区域交叉时的锁竞争关系。
FIleMutex.h:
class FileMutex { public: FileMutex(const string& filename); virtual ~FileMutex(); int lockR(int offset,int len); int lockW(int offset,int len); int lockRWait(int offset,int len,int millseconds); int lockWWait(int offset,int len,int millseconds); int unlock(int offset,int len); private: int fd; };
#include "FileMutex.h" FileMutex::FileMutex(const string& filename) { fd = open(filename.c_str(),O_RDWR| O_CREAT, 0600); if(fd<0){ perror("FileMutex init:"); } cout << "fd:" << fd << endl; assert(fd); } FileMutex::~FileMutex() { if (fd > 0) { close(fd); } } int FileMutex::lockR(int offset, int len) { struct flock lock; lock.l_start = offset; lock.l_len = len; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; int result=fcntl(fd, F_SETLK, &lock); if(result<0){ perror("lockR:"); } return result; } int FileMutex::lockW(int offset, int len) { struct flock lock; lock.l_start = offset; lock.l_len = len; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; return fcntl(fd, F_SETLK, &lock); } int FileMutex::lockRWait(int offset, int len, int millseconds) { struct flock lock; lock.l_start = offset; lock.l_len = len; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; return fcntl(fd, F_SETLKW, &lock); } int FileMutex::lockWWait(int offset, int len, int millseconds) { struct flock lock; lock.l_start = offset; lock.l_len = len; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; return fcntl(fd, F_SETLKW, &lock); } int FileMutex::unlock(int offset, int len) { struct flock lock; lock.l_start = offset; lock.l_len = len; lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; return fcntl(fd, F_SETLK, &lock); } const option options[] = { { "file", required_argument, NULL, 'f' }, { "type", required_argument, NULL, 't' }, { "offset", required_argument, NULL, 'o' }, { "len", required_argument, NULL, 'l' }, { 0, 0, 0, 0 } }; int main(int argc, char **argv) { char cFileName[128]; int type; int offset; int len; int ch; while ((ch = getopt_long(argc, argv, ":f:t:o:l:", options, NULL)) != -1) { switch (ch) { case 'f': strcpy(cFileName, optarg); break; case 't': type = atoi(optarg); break; case 'o': offset = atoi(optarg); break; case 'l': len = atoi(optarg); break; default: break; } } cout << "FileName:" << cFileName << " type:" << type << " offset:" << offset << " len:" << len << endl; FileMutex mutex(cFileName); int lockResult; if (type == 0) { lockResult = mutex.lockR(offset, len); } if (type == 1) { lockResult = mutex.lockW(offset, len); } cout << lockResult << endl; pause(); }
./mutex --file=lock1 --type=0 --offset=0--len=10
./mutex --file=lock1 --type=0 --offset=10 --len=10
两把读锁可以并存。
./mutex --file=lock1 --type=0 --offset=0 --len=10
./mutex --file=lock1 --type=1 --offset=10 --len=10
读锁和写锁区域有交叉,不能并存,有一方将失败
./mutex --file=lock1 --type=0 --offset=0 --len=10
./mutex --file=lock1 --type=1 --offset=11 --len=10
区域没有交叉,可以并存