NAME
flock - 열린 파일에 권고형 락 적용하고 제거하기
SYNOPSIS
#include <sys/file.h>
int flock(int fd, int operation);
DESCRIPTION
fd
로 지정한 열린 파일 디스크립터에 권고형 락을 적용하거나 제거한다. opeartion
인자는 다음 중 하나다.
LOCK_SH
- 공유형 락을 둔다. 어떤 파일에 대해 어느 시점에 여러 프로세스가 공유형 락을 잡을 수 있다.
LOCK_EX
- 배타형 락을 둔다. 어떤 파일에 대해 어느 시점에 한 프로세스만 배타형 락을 잡을 수 있다.
LOCK_UN
- 이 프로세스가 잡은 기존 락을 제거한다.
호환되지 않는 락을 다른 프로세스에서 잡고 있으면 flock()
호출이 블록할 수 있다. 논블로킹 요청을 하려면 위 동작에 LOCK_NB
를 (OR 해서) 포함시키면 된다.
한 파일에 공유형 락과 배타형 락이 동시에 있을 수 없다.
flock()
으로 만든 락은 열린 파일 기술 항목(open(2) 참고)에 연계돼 있다. 따라서 (예를 들어 fork(2)나 dup(2)으로 만들어진) 복제 파일 디스크립터들이 같은 락을 가리키며, 그 파일 디스크립터들 어느 것으로도 락을 변경하거나 놓을 수 있다. 그리고 그 복제 파일 디스크립터들 중 하나에서 명시적으로 LOCK_UN
동작을 하거나 그 파일 디스크립터들이 모두 닫힐 때 락이 해제된다.
한 프로세스에서 open(2)을 (또는 비슷한 함수를) 이용해 같은 파일에 대한 파일 디스크립터를 여러 개 얻은 경우에는 flock()
에서 그 파일 디스크립터들을 별개로 다룬다. 호출 프로세스에서 그 중 하나로 이미 잡은 락을 다른 파일 디스크립터로 잠그려고 시도하면 거부될 수 있다.
프로세스가 한 파일에 대해 (공유 또는 배타) 한 종류의 락만 잡을 수 있다. 이미 잠근 파일에 flock()
호출을 하면 기존 락이 새로운 락 모드로 바뀌게 된다.
flock()
으로 생성된 락이 execve(2)를 거치면서 유지된다.
파일을 연 모드와 상관없이 공유형 락이나 배타형 락을 둘 수 있다.
RETURN VALUE
성공 시 0을 반환한다. 오류 시 -1을 반환하며 오류를 나타내도록 errno
를 설정한다.
ERRORS
EBADF
fd
가 열린 파일 디스크립터가 아니다.EINTR
- 락 획득을 기다리는 동안 핸들러에 잡힌 시그널 전달에 의해 호출이 중단됐다. signal(7) 참고.
EINVAL
operation
이 유효하지 않다.ENOLCK
- 커널에서 락 레코드를 할당할 메모리가 부족하다.
EWOULDBLOCK
- 파일이 잠겨 있으며
LOCK_NB
플래그를 사용했다.
CONFORMING TO
4.4BSD (4.2BSD에서 flock()
호출이 처음 등장). 대부분의 유닉스 시스템에 fcntl(2)을 이용해 구현된 듯한 flock()
버전이 있다.
NOTES
커널 2.0부터 GNU C 라이브러리에서 fcntl(2) 호출로 에뮬레이션하지 않고 자체 시스템 호출로 flock()
을 구현한다. 이 구현 방식에선 flock()
과 fcntl(2)로 두는 락 사이에 상호작용이 없으며 flock()
에서 교착을 탐지하지 않는다. (다만 최근 BSD 계열들 같은 일부 시스템에선 flock()
과 fcntl(2) 락이 상호작용한다.)
flock()
에서 두는 락은 권고형일 뿐이다. 파일에 대한 적절한 권한이 있으면 프로세스에서 얼마든 flock()
사용을 무시하고 파일에 I/O를 수행할 수 있다.
flock()
의 락과 fcntl(2)의 락은 프로세스 포크와 dup(2) 측면에서 동작 방식이 다르다. fcntl(2)로 flock()
을 구현하고 있는 시스템에서는 flock()
의 동작 방식이 이 매뉴얼 페이지의 설명과 달라진다.
락 변환(공유를 배타로, 또는 반대로)이 원자적이라고 보장되지 않는다. 즉, 먼저 기존 락을 제거하고서 새 락을 수립한다. 이 두 단계 사이에서 다른 프로세스의 락 요청이 수락될 수 있으며, 그러면 변환 동작이 블록하게 된다. LOCK_NB
를 지정했으면 실패한다. (이는 원본 BSD의 동작 방식이며 다른 여러 구현체에서도 볼 수 있다.)
NFS 세부 사항
리눅스 커널 2.6.11까지에서 flock()
은 NFS 상의 파일을 잠그지 않는다. (즉, 락의 유효 범위가 로컬 시스템으로 국한되었다.) 충분히 최신 버전의 리눅스를 쓰고 서버에서 지원하는 경우에는 NFS 상에서 동작하는 fcntl(2)의 바이트 범위 락킹을 대신 이용할 수 있었다.
리눅스 2.6.12부터는 NFS 클라이언트에서 전체 파일에 대한 fcntl(2) 바이트 범위 락인 것처럼 에뮬레이션하는 방식으로 flock()
락을 지원한다. 따라서 NFS 상에서 fcntl(2)과 flock()
이 상호작용한다. 그리고 배타적 락을 두려면 파일을 쓰기용으로 열어야 한다.
리눅스 2.6.37부터는 flock()
락을 (그리고 fcntl(2) 바이트 범위 락도) 로컬로 다룰 수 있는 호환 모드를 지원한다. nfs(5)
의 local_lock
옵션 설명 참고.
SEE ALSO
flock(1)
, close(2), dup(2), execve(2), fcntl(2), fork(2), open(2), lockf(3), lslocks(8)
리눅스 커널 소스 트리의 Documentation/filesystems/locks.txt
(옛날 커널에선 Documentation/locks.txt
)
2021-03-22