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
完。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。