2017-02-15 16 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); 
} 
//************************************************************ 
...と、それらは二つの端子

./locktestFIFOに送信することにより、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; 

} 

を読み書きすることによって試みることができます./lck ./fifo messageA ./locktestFIFO ./lck//fifo messageB

LOCKEDが1に設定されていない場合、メッセージが混在します。そうしないと、2つのスレッドがリソースを正しく取得して解放します。

関連する問題