2017-02-15 172 views
1

我试图锁定一些在Linux下的多个应用程序访问的关键资源。如何创建一个文件锁定在linux下超时

所有应用程序在进入临界区时都会在同一个文件上调用acquireLock函数,在离开时调用releaseLock函数。 如果超过超时时间没有获取锁定,则调用者将继续执行其他操作。

下面的代码工程惠特缓慢的进程,但在压力下锁很容易破坏锁是由多个进程获得,所以我想我在某处竞争条件磕磕绊绊。

有人可以指出为什么它不工作,什么是正确的实施?

非常感谢!

MV

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

//************************************************************ 
#define CYCLETIME 1000 
//************************************************************ 

//************************************************************ 
int acquireLock(char *lockFile, int msTimeout) 
{ 

    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 | LOCK_NB) < 0){ 
     usleep(CYCLETIME); 
     cntTimeout++; 
    if(cntTimeout >= msTimeout){ 
     return -1; 
     } 
    } 

    return lockFd; 
} 
//************************************************************* 
void releaseLock (int lockFd) 
{ 
    flock(lockFd, LOCK_UN); 
    close(lockFd); 
} 
//************************************************************ 
+3

它以什么方式完全打破?它是否仅在超时后中断? –

+0

要同步使用某些资源,其逻辑资源或物理资源,还有其他同步方法。 –

+0

@David编辑了这个问题,锁被多个进程获取。 –

回答

1

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

我分享我使用的代码,以防万一它可以帮助别人。

这些都是锁定功能:

/* ----------------------------------------------------------------------- * 
* 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); 
} 
//************************************************************ 

......以及那些可以通过读取和写入一个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; 

} 

在两个终端

./locktestFIFO发送受审./lck ./fifo messageA ./locktestFIFO ./lck ./fifo messageB

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

相关问题