2013-07-17 4 views
16

inter-process mutexes에 flock()을 사용하고 있습니다. 즉, 일부 프로세스는 "some_name"이라는 파일을 임시 디렉토리에 잠그면 구현되는 "some_name"에 대한 잠금을 유지할 수 있습니다.flock() : 경쟁 조건이없는 잠금 파일을 제거 하시겠습니까?

lockfile = "/tmp/some_name.lock"; 
fd = open(lockfile, O_CREAT); 
flock(fd, LOCK_EX); 

do_something(); 

unlink(lockfile); 
flock(fd, LOCK_UN); 

잠금 파일이 어떤 점에서 제거해야, 수백 개의 파일과 임시 디렉토리를 작성 피하기 위해

그러나,이 코드에서 명백한 경쟁 조건이, 프로세스 A, B 및 C와 예 :.

A opens file 
A locks file 
B opens file 
A unlinks file 
A unlocks file 
B locks file (B holds a lock on the deleted file) 
C opens file (a new file one is created) 
C locks file (two processes hold the same named mutex !) 

여기에이 경쟁 조건을 도입하지 않고 어느 시점에서 잠금 파일을 제거하는 방법이 있습니까?

+2

문제는 파일이 리소스를 나타내는 세분화 된 잠금 전략을 구현하려고하지만 공유 된 대용량 리소스 (파일 시스템)에 경합이있는 것입니다. 세분화 된 잠금을 업데이트하기 전에 잠금 파일 디렉토리에 전역 잠금이 필요하거나 잠금 전략을 모두 다시 디자인해야합니다. – jxh

+0

당신은 당신의 필요성을 정교하게 다룰 수 있습니까? 예를 들어, 만약 그들이 모두 동일한 개념적 리소스를 잠그고있는 프로그램은 잘 알려진 파일명을 사용하지 않을까요? –

답변

20

미안 죽은 질문에 회신하는 경우 :이처럼 아이 노드 번호를 모두 복사 fstat를, 그것의 또 다른 복사본을 열고 확인

파일을 잠금 후 :

lockfile = "/tmp/some_name.lock"; 

    while(1) { 
     fd = open(lockfile, O_CREAT); 
     flock(fd, LOCK_EX); 

     fstat(fd, &st0); 
     stat(lockfile, &st1); 
     if(st0.st_ino == st1.st_ino) break; 

     close(fd); 
    } 

    do_something(); 

    unlink(lockfile); 
    flock(fd, LOCK_UN); 

이는 것을 방지 왜냐하면 프로그램이 여전히 파일 시스템에있는 파일에 대한 잠금을 보유하고 있기 때문에 남은 파일이있는 다른 모든 프로그램은 잘못된 inode 번호를 갖기 때문입니다.

사실은 다음과 같은 속성을 사용하여, 상태 기계 모델에 그것을 증명 : P_i가 파일 시스템에 잠겨 기술자가있는 경우

다음 다른 프로세스가 임계 영역에 없습니다.

P_i가 올바른 inode 또는 임계 구역의 통계 뒤에있는 경우 파일 시스템에 디스크립터가 잠겨 있습니다.

+0

위대한 답변, 감사합니다! – arnaud576875

+1

파일을 연결 해제하고 닫은 후에 잠금을 해제 할 수 있습니까? 설명서에 flock이 "fd에 지정된 열린 파일에 자문 잠금을 적용하거나 제거합니다"라고 표시됩니다. – sheerun

+1

누출을 막으려면 fd를 닫지 않아야합니까? –

3

이러한 파일을 잠금 전용으로 사용하고 실제 파일에 쓰지 않는다면 보관 된 잠금에 대한 표시로 디렉토리 항목의 존재를 처리하고 flock을 사용하지 않는 것이 좋습니다.

이렇게하려면 디렉토리 항목을 만들고 이미 존재하는 경우 오류를보고하는 작업을 구성해야합니다. Linux의 경우 의 파일 시스템을 사용하는 경우 O_EXCL에서 open을 전달하면됩니다. 그러나 일부 플랫폼과 일부 파일 시스템 (특히 오래된 NFS)은이를 지원하지 않습니다. , 예를 들면 잠금 파일을 사용하여 잠금 원자 파일을 수행하고 동일한 파일 시스템에 고유 한 파일을 만들 수 있습니다 O_EXCL에 대한 NFS 지원에 의존하지 않도록해야 할

휴대용 프로그램 (다음 man page for open 그러므로 대안을 제시 호스트 이름과 PID를 통합), link (2)을 사용하여 잠금 파일에 대한 링크를 만듭니다. link (2)가 0을 반환하면 잠금이 성공한 것입니다. 그렇지 않은 경우 고유 파일에서 stat (2)을 사용하여 연결 수가 2로 증가했는지 확인하십시오.이 경우 잠금이 성공적으로 수행됩니다.

이렇게 이것은 공식적으로 문서화 된 잠금 계획처럼 보이므로 특정 수준의 지원 및 모범 사례 제안을 나타냅니다. 그러나 나는 다른 접근 방식을 보았습니다. 예를 들어 bzr은 대부분의 장소에서 심볼릭 링크 대신 디렉토리를 사용합니다. its source code에서 인용 :

잠금은 정보 파일을 포함하는 특정 이름, 의 디렉토리에 의해 디스크에 표시됩니다. 잠금을 설정하려면 임시 디렉토리의 이름을 바꿔서 수행하십시오. 임시 디렉토리를 사용하기 때문에 알려진 모든 전송 및 파일 시스템에 대해 중 하나만 잠금을 시도하려고 시도하고 나머지는 실패합니다. (. 일부 파일 시스템 또는 전송은 은 이름 바꾸기 앤 덮어 쓰기 때문에 파일 은 (는) 자기 누가 이겼는지 얘기하게하지 않을 것이다)

한 단점을 위의 방법에 그들이 차단되지 것입니다 : 실패한 잠금 시도는 오류를 발생 시키지만 잠금이 사용 가능할 때까지 대기하지 않습니다. 잠금 경합을 고려할 때 문제가 될 수있는 잠금을 폴링해야합니다. 이 경우, 파일 시스템 기반 접근법을 더 멀리하고, 써드 파티 구현을 대신 사용할 수 있습니다. 하지만 ipc 뮤텍스를 수행하는 방법에 대한 일반적인 질문이 이미 제기되어 있으므로, search for [ipc] [mutex]을 제안하고 결과를 살펴 보겠습니다 (특히 this one).그런데 이러한 태그는 게시물에도 유용 할 수 있습니다.

+5

이 접근법이 겪는 문제점은 프로세스가 잠금을 유지하면서 죽으면 자동으로 잠금을 확보하는 소리가 들리지 않는다는 것입니다. 대조적으로,'flock' 접근법에서 프로세스가 잠금을 유지하면서 죽으면 파일은 파일 시스템에 남게되지만 더 이상 '풀 (flock)'되지 않습니다. 다른 프로세스가 이제 잠금을 획득 할 수 있습니다. – davidg

+0

@ davidg : 유효 지점입니다. 일부 구현은 잠금 파일 이름 또는 잠금 디렉토리의 잘 알려진 파일에 링크되는 파일에 잠금 프로세스의 타임 스탬프 및/또는 pid를 작성합니다. 그렇게하면 해당 ID를 가진 프로세스가 아직 살아 있는지 확인할 수 있으며 주어진 시간이 지나면 잠금을 만료시킬 수도 있습니다. – MvG