首页 > 代码库 > linux文件锁
linux文件锁
文件锁,控制颗粒度可以到文件的一行记录,方便数据库使用。文件锁用于进程间同步。
开发环境:cetos6.3(64),eclipse helios +cdt.
首先,定义一个文件锁类。
CFileLockHandler.h:
/* * CFileLockHandler.h * * Created on: 2014-9-28 * Author: root */#ifndef CFILELOCKHANDLER_H_#define CFILELOCKHANDLER_H_#include <fcntl.h>class CFileLockHandler{public: CFileLockHandler(); ~CFileLockHandler(); int InitialFileLock(const char* pchLockFile); void MutexOnFileRead(off_t iBeginIndex, off_t iLen); void MutexOnFileWrite(off_t iBeginIndex, off_t iLen); void FileMutexOff(off_t iBeginIndex, off_t iLen); char* GetErrMsg() { return m_szErrMsg;}private: char m_szLockFileName[256]; int m_iFileLockFd; struct flock m_stFLock; char m_szErrMsg[512]; void CleanupFileLock();};#endif /* CFILELOCKHANDLER_H_ */
CFileLockHandler.cpp:
/* * CFileLockHandler.cpp * * Created on: 2014-9-28 * Author: root */#include <stdlib.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <syslog.h>#include "CFileLockHandler.h"CFileLockHandler::CFileLockHandler(){ memset(m_szLockFileName, 0x0, sizeof(m_szLockFileName)); memset(m_szErrMsg, 0x0, sizeof(m_szErrMsg)); m_iFileLockFd = -1;}CFileLockHandler::~CFileLockHandler(){ //CleanupFileLock();}int CFileLockHandler::InitialFileLock(const char* pchLockFile){ strncpy(m_szLockFileName, pchLockFile, sizeof(m_szLockFileName)-1); m_iFileLockFd = open(m_szLockFileName, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); if(m_iFileLockFd < 0) { snprintf(m_szErrMsg, sizeof(m_szErrMsg), "open lock file:%s fail:%s", m_szLockFileName, strerror(errno)); return -1; } return 0;}void CFileLockHandler::CleanupFileLock(){ if(m_iFileLockFd > 0) close(m_iFileLockFd);}void CFileLockHandler::MutexOnFileRead(off_t iBeginIndex, off_t iLen){ //DEBUG_LOG( "MutexOnFileRead" ); m_stFLock.l_type = F_RDLCK; m_stFLock.l_start = iBeginIndex; m_stFLock.l_whence = SEEK_SET; m_stFLock.l_len = iLen; int iTryTimes = 0; int iRet = 0; //fprintf(stderr, "waitting rlock:%lld, %lld, %lld, %d\n", (long long)getpid(), (long long)iBeginIndex, (long long)errno, iRet); //如果文件锁被请他进程占有,很多时候代码执行到这里,函数会阻塞。直到获取到文件锁,当然函数也有出现错误而立刻返回的情况。 while ((iRet = fcntl(m_iFileLockFd, F_SETLKW, &m_stFLock)) < 0) { fprintf(stderr, "xxxxxxxxxxxxxxxxxxx:%lld, %lld\n", (long long)getpid(), (long long)errno); //positive keep locking if(EAGAIN == errno || EACCES == errno || EINTR == errno) continue; else if(EBADF == errno || EINVAL == errno || EOVERFLOW == errno || EDEADLK == errno) { openlog("tuan_server", LOG_CONS|LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "CFileLockHandler::MutexOnFileRead dead error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); printf("CFileLockHandler::MutexOnFileRead dead error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); exit(-1); } //other error else { if(5 >= ++iTryTimes) continue; openlog("tuan_server", LOG_CONS|LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "CFileLockHandler::MutexOnFileRead unhandled error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); printf("CFileLockHandler::MutexOnFileRead unhandled error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); break; } /*if(errno != EINTR) { //ERROR_LOG( "MutexOnFileRead fcntl failed.err[%s]", strerror(errno) ); return; }*/ } //fprintf(stderr, "in rlock:%lld, %lld, %lld, %d\n", (long long)getpid(), (long long)iBeginIndex, (long long)errno, iRet);}void CFileLockHandler::MutexOnFileWrite(off_t iBeginIndex, off_t iLen){ //DEBUG_LOG( "MutexOnFileWrite" ); m_stFLock.l_type = F_WRLCK; m_stFLock.l_start = iBeginIndex; m_stFLock.l_whence = SEEK_SET; m_stFLock.l_len = iLen; int iTryTimes = 0; int iRet = 0; //fprintf(stderr, "waitting wlock:%lld, %lld, %lld, %d\n", (long long)getpid(), (long long)iBeginIndex, (long long)errno, iRet); //如果文件锁被请他进程占有,很多时候代码执行到这里,函数会阻塞。直到获取到文件锁,当然函数也有出现错误而立刻返回的情况。 while ((iRet = fcntl(m_iFileLockFd, F_SETLKW, &m_stFLock)) < 0) { fprintf(stderr, "xxxxxxxxxxxxxxxxxxx:%lld, %lld\n", (long long)getpid(), (long long)errno); //positive keep locking if(EAGAIN == errno || EACCES == errno || EINTR == errno) continue; else if(EBADF == errno || EINVAL == errno || EOVERFLOW == errno || EDEADLK == errno) { openlog("tuan_server", LOG_CONS|LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "CFileLockHandler::MutexOnFileWrite dead error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); printf("CFileLockHandler::MutexOnFileWrite dead error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); exit(-1); } //other error else { if(5 >= ++iTryTimes) continue; openlog("tuan_server", LOG_CONS|LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "CFileLockHandler::MutexOnFileWrite unhandled error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); printf("CFileLockHandler::MutexOnFileWrite unhandled error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); break; } /*if(errno != EINTR) { //ERROR_LOG( "MutexOnFileWrite fcntl failed.err[%s]", strerror(errno) ); return; }*/ } //fprintf(stderr, "in wlock:%lld, %lld, %lld, %d\n", (long long)getpid(), (long long)iBeginIndex, (long long)errno, iRet);}void CFileLockHandler::FileMutexOff(off_t iBeginIndex, off_t iLen){ //DEBUG_LOG( "FileMutexOff" ); m_stFLock.l_type = F_UNLCK; m_stFLock.l_start = iBeginIndex; m_stFLock.l_whence = SEEK_SET; m_stFLock.l_len = iLen; int iTryTimes = 0; int iRet = 0; //fprintf(stderr, "before unlock:%lld, %lld, %lld, %d\n", (long long)getpid(), (long long)iBeginIndex, (long long)errno, iRet); while ((iRet = fcntl(m_iFileLockFd, F_SETLKW, &m_stFLock)) < 0) { fprintf(stderr, "xxxxxxxxxxxxxxxxxxx:%lld, %lld\n", (long long)getpid(), (long long)errno); if(EAGAIN == errno || EACCES == errno || EINTR == errno) continue; else if(EBADF == errno || EINVAL == errno || EOVERFLOW == errno || EDEADLK == errno) { openlog("tuan_server", LOG_CONS|LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "CFileLockHandler::MutexOnFileWrite dead error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); printf("CFileLockHandler::MutexOnFileWrite dead error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); exit(-1); } //other error else { if(5 >= ++iTryTimes) continue; openlog("tuan_server", LOG_CONS|LOG_PID, LOG_DAEMON); syslog(LOG_ERR, "CFileLockHandler::MutexOnFileWrite unhandled error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); printf("CFileLockHandler::MutexOnFileWrite unhandled error, iRet=%d, errno:%d, iBeginIndex:%zd", iRet, errno, iBeginIndex); break; } /*if(errno != EINTR) { //ERROR_LOG( "FileMutexOff fcntl failed.err[%s]", strerror(errno) ); return; }*/ } //fprintf(stderr, "after unlock:%lld, %lld, %lld, %d\n", (long long)getpid(), (long long)iBeginIndex, (long long)errno, iRet);}
主程序test.cpp:
//============================================================================// Name : test.cpp// Author : // Version :// Copyright : Your copyright notice// Description : Hello World in C++, Ansi-style//============================================================================#include "CFileLockHandler.h"#include <stdio.h>#include <iostream>using namespace std;int main() { int iRet; CFileLockHandler pcLockHandler; pid_t pid = fork(); if( pid < 0 ) { //出错 fprintf( stderr, "fork failed.\n" ); return 1; } else if( pid > 0 ) { //父进程 iRet=pcLockHandler.InitialFileLock("/tmp/test.lock"); if(0!=iRet) { printf("InitialFileLock fail.\n"); return -1; } pcLockHandler.MutexOnFileWrite(0,1); printf("get write-lock first\n"); pcLockHandler.MutexOnFileWrite(0,1); printf("get write-lock second\n"); cout << "!!!Hello World!!!" << endl; } else { //子进程 iRet=pcLockHandler.InitialFileLock("/tmp/test.lock"); if(0!=iRet) { printf("子进程InitialFileLock fail.\n"); return -1; } pcLockHandler.MutexOnFileWrite(0,1); printf("子进程get write-lock first\n"); pcLockHandler.MutexOnFileWrite(0,1); printf("子进程get write-lock second\n"); cout << "子进程!!!Hello World!!!" << endl; } printf("pls enter any key...\n"); getchar(); return 0;}
运行效果如下,首先父进程两次都能获取到文件锁写。按回车键后,父进程释放文件锁写。子进程接着获取到文件锁写。
有用的命令:pkill,此命令用来删除所有调试时运行而忘记关闭的进程。
pkill -9 test
完。
linux文件锁
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。