플록 (): 레이스 조건 없이 잠긴 파일 제거?
flock()을 사용하여 mutexes라는 이름의 프로세스 간에 잠금을 설정합니다(즉, 일부 프로세스는 some_name이라는 이름의 파일을 임시 디렉토리에 잠그는 방식으로 구현됩니다).
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 !)
이 레이스 조건을 도입하지 않고 어느 시점에서 잠금 파일을 제거할 수 있는 방법이 있습니까?
질문에 답하면 죄송합니다.
파일을 잠근 후 다른 복사본을 열고 fstat 두 복사본을 모두 열고 다음과 같이 inode 번호를 확인합니다.
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);
이렇게 하면 프로그램이 파일 시스템에 남아 있는 파일에 대한 잠금을 유지할 경우 남은 파일이 있는 다른 모든 프로그램의 아이노드 번호가 잘못 표시되기 때문에 경쟁 상태를 방지할 수 있습니다.
저는 실제로 다음과 같은 속성을 사용하여 상태 기계 모델에서 증명했습니다.
P_i에 파일 시스템에 디스크립터가 잠겨 있으면 다른 프로세스는 중요 섹션에 없습니다.
P_i가 오른쪽 inode를 가진 stat 뒤에 있거나 critical 섹션에 있는 경우 파일 시스템에서 디스크립터가 잠겨 있습니다.
- 유닉스에서는 파일이 열리는 동안 파일을 삭제할 수 있습니다. 파일 설명자 목록에 있는 모든 프로세스가 끝날 때까지 해당 노드는 유지됩니다.
- 유닉스에서는 링크 수가 0이 되면 모든 디렉터리에서 파일이 제거되었는지 확인할 수 있습니다.
따라서 이전/새 파일 경로의 ino-value를 비교하는 대신 이미 열려 있는 파일의 nlink count를 확인하기만 하면 됩니다.이 파일은 단순한 임시 잠금 파일일 뿐 실제 뮤텍스 리소스나 장치가 아니라고 가정합니다.
lockfile = "/tmp/some_name.lock";
for(int attempt; attempt < timeout; ++attempt) {
int fd = open(lockfile, O_CREAT, 0444);
int done = flock(fd, LOCK_EX | LOCK_NB);
if (done != 0) {
close(fd);
sleep(1); // lock held by another proc
continue;
}
struct stat st0;
fstat(fd, &st0);
if(st0.st_nlink == 0) {
close(fd); // lockfile deleted, create a new one
continue;
}
do_something();
unlink(lockfile); // nlink :=0 before releasing the lock
flock(fd, LOCK_UN);
close(fd); // release the ino if no other proc
return true;
}
return false;
만약 당신이 이 파일들을 잠금에만 사용하고 실제로 그것들에 쓰지 않는다면, 나는 당신이 디렉토리 엔트리의 존재 자체를 보류된 잠금에 대한 표시로 취급하고, 아예 사용하지 말 것을 제안합니다.
이를 위해서는 디렉토리 항목을 생성하고 오류가 이미 존재하는 경우 오류를 보고하는 작업을 구성해야 합니다.Linux 및 대부분의 파일 시스템에서 전달O_EXCL
이것을 위해 일할 것입니다.그러나 일부 플랫폼 및 일부 파일 시스템(특히 오래된 NFS)에서는 이를 지원하지 않습니다.따라서 man 페이지는 다음과 같은 대안을 제시합니다.
잠금 파일을 사용하여 원자 파일 잠금을 수행하고 NFS 지원에 의존하지 않아야 하는 휴대용 프로그램
O_EXCL
, 는 동일한 파일 시스템에 고유한 파일(예: 호스트 이름과 PID 통합)을 생성하고 (2)를 사용하여 잠금 파일에 대한 링크를 만들 수 있습니다.(2)가 0을 반환하면 잠금이 성공한 것입니다.그렇지 않으면 고유 파일에서 (2)를 사용하여 링크 수가 2로 증가했는지 확인합니다. 이 경우 잠금도 성공적입니다.
따라서 이것은 공식적으로 문서화된 잠금 체계처럼 보이며 따라서 일정 수준의 지원과 모범 사례 제안을 나타냅니다.하지만 저는 다른 접근법들도 보았습니다. 예를 들어, 대부분의 장소에서 symlink 대신 디렉토리를 사용합니다.소스 코드에서 인용:
잠금은 디스크에서 정보 파일을 포함하는 특정 이름의 디렉토리로 표시됩니다.잠금은 임시 디렉토리의 이름을 제자리로 변경하여 수행됩니다.알려진 모든 전송 및 파일 시스템에 대해 한 번만 잠금을 요청해도 성공하고 다른 한 번만 실패할 것으로 생각하기 때문에 임시 디렉토리를 사용합니다. (일부 파일 시스템 또는 전송에는 이름 변경 및 덮어쓰기 기능만 있어 누가 이겼는지 구분하기 어렵기 때문에 파일에서는 사용할 수 없습니다.)
위의 접근 방식의 한 가지 단점은 차단하지 않는다는 것입니다. 잠금 시도에 실패하면 오류가 발생하지만 잠금을 사용할 수 있을 때까지 기다리지 않는다는 것입니다.잠금을 폴링해야 하므로 잠금 경합으로 문제가 될 수 있습니다.이 경우 파일 시스템 기반 접근 방식에서 벗어나 타사 구현 방식을 사용하는 것이 좋습니다.그러나 ipc mutex를 어떻게 하는지에 대한 일반적인 질문은 이미 물었으므로, 특히 이번 것은 결과물을 검색해서 보는 것을 제안합니다.그런데, 이 태그들은 당신의 게시물에도 유용할 수 있습니다.
언급URL : https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition
'programing' 카테고리의 다른 글
Pandas read_xml() 메서드 테스트 전략 (0) | 2023.10.27 |
---|---|
평원 C에서 UTF-8을 탐지하는 방법은? (0) | 2023.10.27 |
부트스트랩과 함께 필드셋 범례 사용 (0) | 2023.10.27 |
Python git 저장소를 복제하는 방법 (0) | 2023.10.27 |
자동 완료 시 트리거된 이벤트가 있습니까? (0) | 2023.10.27 |