首页 > 代码库 > 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文件锁