Chapter 07. 파일 및 레코드 잠금
리눅스 프로그래밍 원리와 실제 - 창병모 교수님
7.1 파일 잠금
1) 파일 및 레코드 잠금의 필요성
- 프로세스 사이에 데이터는 한 프로세스가 파일에 쓴 내용을 다른 프로세스가 읽음으로써 데이터를 주고받을 수 있음
- 문제점
- 한 프로세스가 파일 내용을 수정하는 동안에 다른 프로세스가 그 파일을 읽는 경우
- 두 개의 프로세스가 하나의 파일에 동시에 접근하여 데이터를 쓰는 경우
- 잠금(lock):
- 한 프로세스가 그 영역을 읽거나 수정할 때 다른 프로세스의 접근을 제한
- 잠근된 영역에 한 번에 하나의 프로세스만 접근
- 특히 레코드 쓰기(혹은 수정)를 할 경우 대상 레코드에 대해 잠금을 해서 다른 프로세스가 접근하지 못하게 해야 함
접근하는 프로세스 A가 대상 레코드에 잠금을 하는 경우: 수행 후 프로세스 B가 레코드를 접근하려고 하면
해당 레코드는 이미 잠금 상태이기 때문에 프로세스 A가 잠금을 풀 때까지 기다려야 함
Q. 파일 전체에 대해 잠금을 하지 않고 레코드 잠금을 하는 이유
A. 많은 사용자들이 동시에 접근해 하나의 파일을 조작해야 하는 경우, 파일 전체를 잠금하면 속도 등의 성능에 좋지 않은 영향을 미치게 됨. 이럴 경우에는 파일 전체를 잠금 하는 것보다 해당 프로세스가 접근하는 일부분만을 잠금하고 나머지 부분은 다른 프로세스에서 접근 가능하도록 하는 게 동시처리가 가능하기 때문에 보다 효율적임
2) 파일 잠금 flock()
- 파일 잠금(file locking): 하나의 파일 전체에 잠금을 하는 것
- 어떤 파일에 파일 잠금을 원하는 프로세스는 해당 파일에 공유 잠금(shared lock) 또는 배타 잠금(exclusive lock)을 할 수 있음
파일의 현재 잠금 상태 | 공유 잠금 요청 | 배타 잠금 요청 |
잠금 없음 | 승인 | 승인 |
하나 이상의 공유 잠금 | 승인 | 거절 |
하나의 배타 잠금 | 거절 | 거절 |
- 열린 파일에 대해서 잠금을 적용하거나 해제하는 일을 수행
int flock(int id, int operation)
잠금 명령어 | 설명 |
LOCK_SH | 공유 잠금으로 한 개 이상의 프로세스들이 파일에 대한 공유 잠금이 가능 |
LOCK_EX | 배타 잠금으로 한번에 하나의 프로세스만이 파일에 대한 배타 잠금을 할 수 있음. 파일에 이미 배타 잠금이 있으면 기다림 |
LOCK_UN | 파일에 걸려 있는 잠금을 해제 |
LOCK_NB | 파일에 잠금이 걸려 있으면 기다리지 않고 반환하여 이런 경우에 errno에 EWOULBLOCK가 설정됨. 잠금을 확인하고 다른 일을 할 때 유용함 |
7.2 레코드 잠금
1) 읽기 잠금과 쓰기 잠금
- 읽기 잠금: 파일 전체에 대해 잠금
- 레코드 잠금: 파일의 일부 영역(레코드)에 대해서 잠금
- fcntl() 함수: 파일 및 레코드 잠금을 할 수 있음
- 잠금의 종류
- F_RDLCK: 여러 프로세스가 공유 가능한 읽기 잠금
- F_WRLCK: 한 프로세스만 가질 수 있는 배타적인 쓰기 잠금
대상 영역의 현재 잠금 상태 | 읽기 잠금 요청 | 쓰기 잠금 요청 |
잠금 없음 | 승인 | 승인 |
하나 이상의 읽기 잠금 | 승인 | 거절 |
하나의 쓰기 잠금 | 거절 | 거절 |
2) 레코드 잠금 fcntl()
- cmd에 따라 지정된 영역에 대한 잠금 검사 혹은 잠금 설정
- 성공하면 0 실패하면 -1을 반환
int fcntl(int fd, int cmd, struct flock *lock)
- cmd
- F_GETLK: 잠금 검사
- F_SETLK: 잠금 설정 혹은 해제
- F_SETLKW: 잠금 설정(블로킹 버전) 혹은 해제
- flock 구조체: 요청할 잠금을 위해 필요한 여러 가지 정보 명시
struct flock{
short l_type; // 잠금 종류: F_RDLCK, F_WRLCK, F_UNLCK
off_t l_start; // 잠금 시작 위치: 바이트 오프셋
short l_whence; // 기준 위치: SEEK_SET(파일 시작), SEEK_CUR(현재 파일 위치), SEEK_END(파일 끝)
off_t l_len; // 잠금 길이: 바이트 수 (0이면 파일 끝까지)
pid_t l_pid; // 짐금한 프로세스 번호
}
- 레코드 잠금을 이용해 파일 잠금도 가능
- 파일 전체에 대해 잠금을 하려면, 파일의 처음부터 끝까지 잠금을 하면 됨
- 파일 전체에 대해 잠금하기 위해서는 잠금 영역을 지정할 때 l_start를 파일 시작 위치로 정하고 잠금 영역의 길이 l_lendmf 0으로 표시하면 됨
7.3 잠금 함수
1) 잠금 함수 lockf()
- fcntl()함수가 복잡하기 때문에 간단하게 사용하기 위해 만듦
- cmd에 따라 잠금 설정, 잠금 검사 혹은 잠금 해제를 함 → 읽기 잠금은 X
- 잠금 영역: 현재 파일 위치부터 len 길이만큼
- F_LOCK: 지정된 영역에 쓰기 잠금을 설정. 이미 잠금이 설정되어 있으면 잠금이 해제될 때까지 기다림
- F_TLOCK: 지정된 영역에 대해 잠금을 설정. 이미 잠금이 설정되어 있으면 기다리지 않고 오류(-1)를 반환
- F_TEST: 지정된 영역이 잠금 되어 있는지 검사. 잠금이 설정되어 있지 않으면 0을 반환하고 잠금이 설정되어 있으면 -1을 반환
- F_ULOCK: 지정된 영역의 잠금을 해제
- 잠금 영역: 현재 파일 위치부터 len 길이만큼
- 파일 내의 어떤 영역에 대해 잠금을 하려면 먼저 lseek() 함수를 이용해 현재 파일 위치를 그 영역의 시작 위치로 이동한 후에 잠금 할 때 영역의 길이를 명시
7.4 권고 잠금과 강제 잠금
1) 권고 잠금과 강제 잠금
- 권고 잠금(advisory locking)
- 이미 잠금 된 파일 영역에 대해서도 잠금 규칙을 무시하고 읽거나 쓸 수 있음
- 잠금을 할 수 있지만 강제되지는 않음
- 모든 관련 프로세스들이 자발적으로 잠금 규칙을 준수
- BSD, Mac OS, Linux 운영체제
- 강제 잠금(mandatory locking)
- 잠금된 파일 영역에 대해 자금 규칙을 무시하고 읽거나 쓸 수 없음
- 커널이 잠금 규칙을 강제하므로 시스템의 부하가 증가
- System V, 솔라리스 계열 운영체제에서 제공
- Linux의 경우 파일 시스템을 파운트 할 때 "-o mand" 옵션을 사용해서 마운트해야 제공됨
Q. 어떻게 구분?
A. 보통 파일에 대해 잠금을 하면 이는 모두 권고 잠금을 한 것임
2) 강제 잠금
- 강제 장금을 하는 방법: 해당 파일에 대해 set-group-ID 비트를 설정하고 group-execute 비트를 끄면 됨
$ chmod 2644 mandatory.txt
$ ls -l madatory.txt
-rw-r-Sr-- euna euna 160 1월 31일 11:48 mandatory.txt
- 강제 잠금 규칙
대상 영역의 현재 잠금 상태 | 넌블로킹 파일 디스크립터 | 블로킹 파일 디스크립터 | ||
읽기 | 쓰기 | 읽기 | 쓰기 | |
읽기 잠금 | OK | 오류(EAGAIN) | OK | 블로킹 |
쓰기 잠금 | 오류(EAGAIN) | 오류(EAGAIN) | 블로킹 | 블로킹 |
- 넌블로킹 모드: 읽기 잠금 된 영역에 대해 잠금 규칙을 무시하고 쓰기를 시도하려하면 오류가 발생되고 errno가 EAGAIN으로 설정
- 쓰기 잠금 된 영역에 잠금 규칙을 무시하고 읽거나 쓰려고하면 오류 발생
- 읽기 잠금된 영역에 대해 읽기는 허용
- 블로킹 모드: 잠금 규칙을 무시하고 읽거나 쓰려고 할 때 오류가 발생되는 대신에 읽기 혹은 쓰기가 블로킹되어 기다림
'Study > Linux' 카테고리의 다른 글
[LinuxProgramming] Chapter 09. 프로세스 제어 (0) | 2022.06.06 |
---|---|
[LinuxProgramming] Chapter 08. 프로세스 (0) | 2022.06.05 |
[LinuxProgramming] Chapter 06. 파일 시스템 (0) | 2022.04.25 |
[LinuxProgramming] Chapter 05. 파일 입출력 (0) | 2022.04.25 |
[Linux] GRUB 부트로더 (0) | 2021.10.25 |