C linux下如何创建带超时的文件锁

C linux下如何创建带超时的文件锁,c,linux,multithreading,C,Linux,Multithreading,我试图锁定linux下多个应用程序访问的一些关键资源 所有应用程序在进入关键部分时将调用同一文件上的acquireLock函数,在离开时调用releaseLock函数。 如果超过一段时间未获得锁,则调用方将继续执行其他操作 下面的代码在进程较慢的情况下工作,但在压力下锁很容易被打破锁是由多个进程获得的,所以我想我在某个地方遇到了竞争条件 有人能告诉我为什么它不起作用,正确的实现方式是什么吗 非常感谢 MV #包括 #包括 #包括 #包括 #包括 #包括 #包括 //***************

我试图锁定linux下多个应用程序访问的一些关键资源

所有应用程序在进入关键部分时将调用同一文件上的acquireLock函数,在离开时调用releaseLock函数。 如果超过一段时间未获得锁,则调用方将继续执行其他操作

下面的代码在进程较慢的情况下工作,但在压力下锁很容易被打破锁是由多个进程获得的,所以我想我在某个地方遇到了竞争条件

有人能告诉我为什么它不起作用,正确的实现方式是什么吗

非常感谢

MV

#包括
#包括
#包括
#包括
#包括
#包括
#包括
//************************************************************
#定义CYCLETIME 1000
//************************************************************
//************************************************************
int acquireLock(char*lockFile,int msTimeout)
{
int lockFd;
int cntTimeout=0;
如果((lockFd=open(lockFile,O|u CREAT | O| u RDWR,S|u IRWXU | S|IRWXG | S|u IRWXO))<0)
返回-1;
而(群集(锁定FD,锁定EX |锁定NB)<0){
usleep(周期时间);
cntTimeout++;
如果(CNTTEOUT>=msTimeout){
返回-1;
}
}
返回锁fd;
}
//*************************************************************
无效释放锁(内部锁FD)
{
鸥群(lockFd,LOCK_UN);
关闭(锁定FD);
}
//************************************************************

看来错误在代码的另一部分,锁按预期工作

我分享我正在使用的代码,以防它对其他人有帮助

这些是锁定功能:

/* ----------------------------------------------------------------------- *
 *  Code derived by the flock.c in the "util-linux" ubuntu package 
 *  by  Peter Anvin 
 * ----------------------------------------------------------------------- */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/file.h>
#include <sys/time.h>
#include <signal.h>

//************************************************************
static sig_atomic_t timeout_expired = 0;
//************************************************************

static void timeout_handler(int sig)
{
  (void)sig;

  timeout_expired = 1;
}


//************************************************************
int acquireLock(char *lockFile, int msTimeout) 
{
    struct itimerval timeout, old_timer;
    struct sigaction sa, old_sa;
    int err;
    int sTimeout = msTimeout/1000;
    memset(&timeout, 0, sizeof timeout);

    timeout.it_value.tv_sec = sTimeout;
    timeout.it_value.tv_usec = ((msTimeout-(sTimeout*1000))*1000);

    memset(&sa, 0, sizeof sa);

    sa.sa_handler = timeout_handler;
    sa.sa_flags   = SA_RESETHAND;
    sigaction(SIGALRM, &sa, &old_sa);
    setitimer(ITIMER_REAL, &timeout, &old_timer);


    int lockFd;
    int cntTimeout = 0;

    if ((lockFd = open(lockFile, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO))  < 0)
        return -1;

    while (flock(lockFd, LOCK_EX))
    {
        switch( (err = errno) ) {
            case EINTR:         /* Signal received */
                if ( timeout_expired )
                    setitimer(ITIMER_REAL, &old_timer, NULL); /* Cancel itimer */
                    sigaction(SIGALRM, &old_sa, NULL); /* Cancel signal handler */
                    return -1;      /* -w option set and failed to lock */
                continue;           /* otherwise try again */
            default:            /* Other errors */
                return -1;  
        }
    }   

    setitimer(ITIMER_REAL, &old_timer, NULL); /* Cancel itimer */
    sigaction(SIGALRM, &old_sa, NULL); /* Cancel signal handler */

    return lockFd;
}
//***************************************************************
void releaseLock (int lockFd) 
{
    flock(lockFd, LOCK_UN);
    close(lockFd);
}
//************************************************************
/*--------------------------------------------------------------------------------------*
*“util linux”ubuntu包中flock.c派生的代码
*彼得·安文
* ----------------------------------------------------------------------- */
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//************************************************************
静态信号原子超时过期=0;
//************************************************************
静态无效超时处理程序(int sig)
{
(无效)sig;
超时时间=1;
}
//************************************************************
int acquireLock(char*lockFile,int msTimeout)
{
结构itimerval超时,旧计时器;
结构sigaction sa,old_sa;
INTERR;
int sTimeout=msTimeout/1000;
memset(&timeout,0,sizeof timeout);
timeout.it_value.tv_sec=刺激;
timeout.it_value.tv_usec=((msTimeout-(sTimeout*1000))*1000);
memset(&sa,0,sizeof sa);
sa.sa_handler=超时_handler;
sa.sa_flags=sa_RESETHAND;
sigaction(SIGALRM、sa和old_sa);
setitimer(ITIMER\U REAL、超时和旧定时器);
int lockFd;
int cntTimeout=0;
如果((lockFd=open(lockFile,O|u CREAT | O| u RDWR,S|u IRWXU | S|IRWXG | S|u IRWXO))<0)
返回-1;
while(flock(lockFd,LOCK_EX))
{
开关((err=errno)){
案例EINTR:/*接收到信号*/
如果(超时\u已过期)
setitimer(ITIMER\u REAL和old\u timer,NULL);/*取消ITIMER*/
sigaction(SIGALRM和old_sa,NULL);/*取消信号处理程序*/
返回-1;/*-w选项集,无法锁定*/
继续;/*否则重试*/
默认值:/*其他错误*/
返回-1;
}
}   
setitimer(ITIMER\u REAL和old\u timer,NULL);/*取消ITIMER*/
sigaction(SIGALRM和old_sa,NULL);/*取消信号处理程序*/
返回锁fd;
}
//***************************************************************
无效释放锁(内部锁FD)
{
鸥群(lockFd,LOCK_UN);
关闭(锁定FD);
}
//************************************************************
。。。这些可以通过读写FIFO来尝试

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "lock.h"

#define LOCKED 1

void main(int argc, char **argv)

{
    const char *filename;
    const char *fifo_name;
    const char *message;
    int lockfd, fifoHandle;
    filename = argv[1];
    fifo_name = argv[2];
    message = argv[3];
    char bufin[1024];
    char bufout[1024];
    struct stat st;
    int bufsize = strlen(message)+1;
    int sleeptime = 0;
    int j = 0;

    if (stat(fifo_name, &st) != 0)
        mkfifo(fifo_name, 0666);

    while (1){

    if (LOCKED)
        lockfd=acquireLock(filename, 15000);

    if (lockfd==-1)
        printf("timeout expired \n");

    fifoHandle= open(fifo_name, O_RDWR);
    strcpy(bufin, message);
    bufin[bufsize-1] = 0x0;
    write(fifoHandle, bufin, sizeof(char)*bufsize);
    sleeptime = rand() % 100000;
    usleep(sleeptime);
    read(fifoHandle, &bufout, sizeof(char)*(bufsize+1));
    printf("%s - %d \n", bufout, j);
    j= j+1;
    if (LOCKED)
        releaseLock(lockfd);

    sleeptime = rand() % 10000;

    }

    unlink(fifo_name);


    return;

}
#包括
#包括
#包括
#包括
#包括“lock.h”
#定义锁定1
void main(整型argc,字符**argv)
{
常量字符*文件名;
常量字符*fifo_名称;
const char*消息;
国际洛克菲德,第五把手;
filename=argv[1];
fifo_name=argv[2];
message=argv[3];
char-bufin[1024];
char bufout[1024];
结构统计;
int bufsize=strlen(消息)+1;
int sleeptime=0;
int j=0;
如果(统计(fifo_名称和st)!=0)
mkfifo(fifo_名称,0666);
而(1){
如果(已锁定)
lockfd=acquireLock(文件名,15000);
如果(lockfd==-1)
printf(“超时已过期\n”);
fifo句柄=打开(fifo\u名称,O\u RDWR);
strcpy(bufin,消息);
bufin[bufsize-1]=0x0;
写入(fifoHandle、bufin、sizeof(char)*bufsize);
sleeptime=rand()%100000;
usleep(睡眠时间);
读取(fifoHandle和bufout,sizeof(char)*(bufsize+1));
printf(“%s-%d\n”,bufout,j);
j=j+1;
如果(已锁定)
释放锁(lockfd);
sleeptime=rand()%10000;
}
取消链接(fifo_名称);
返回;
}
通过发送两个终端

./locktestFIFO./lck./fifo消息a ./locktestFIFO./lck./fifo消息b


如果未将LOCKED设置为1,则消息将混淆,否则两个线程将正确获取并释放资源。

它以何种方式断开?它是否只有在超时后才会中断?要同步某些资源的使用,无论是其逻辑资源还是物理资源,还有其他同步方法。@David,编辑了问题,锁是由多个进程获得的。您能给我们提供足够的代码来复制该问题吗?您所声称的特定故障模式似乎是不可能的。@David是的,我将尝试编写一个示例
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "lock.h"

#define LOCKED 1

void main(int argc, char **argv)

{
    const char *filename;
    const char *fifo_name;
    const char *message;
    int lockfd, fifoHandle;
    filename = argv[1];
    fifo_name = argv[2];
    message = argv[3];
    char bufin[1024];
    char bufout[1024];
    struct stat st;
    int bufsize = strlen(message)+1;
    int sleeptime = 0;
    int j = 0;

    if (stat(fifo_name, &st) != 0)
        mkfifo(fifo_name, 0666);

    while (1){

    if (LOCKED)
        lockfd=acquireLock(filename, 15000);

    if (lockfd==-1)
        printf("timeout expired \n");

    fifoHandle= open(fifo_name, O_RDWR);
    strcpy(bufin, message);
    bufin[bufsize-1] = 0x0;
    write(fifoHandle, bufin, sizeof(char)*bufsize);
    sleeptime = rand() % 100000;
    usleep(sleeptime);
    read(fifoHandle, &bufout, sizeof(char)*(bufsize+1));
    printf("%s - %d \n", bufout, j);
    j= j+1;
    if (LOCKED)
        releaseLock(lockfd);

    sleeptime = rand() % 10000;

    }

    unlink(fifo_name);


    return;

}