둘 이상의 프로세스/스레드가 동시에 실행되고 있을 때, 타이밍 등에 의해서 의도치 않은 결과를 야기할 수 있는 상태를 의미
둘 이상의 프로세스/스레드가 동시에 접근하면 안되는 Resource가 존재하는 코드 영역을 의미
#include <sys/file.h>
int flock(int fd, int operation);
파일 디스크립터
Lock 설정
LOCK_SH
공유 Lock 시도
LOCK_EX
상호배제 Lock 시도
LOCK_UN
점유Lock 해제
LOCK_NB
Non-block(Lock될 때까지 대기하지 않음)
0
-1(LOCK_NB가 Set되어 있을 때만 실패반환이 발생할 수 있음)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/file.h>
#define TARGET_FILE "file"
#define isNonBlock(x) ( strcmp(x, "nb") == 0)
#define isSameStr(x, y) ( strcmp(x,y) == 0 )
#define isFdOpened(x) ( (fd >= 0) && (fd != fileno(stdin)) && (fd != fileno(stdout)) && (fd != fileno(stderr)) )
static void write_file(bool isNonBlock)
{
int fd = -1, operation;
char *str = "Hello, World~!\n";
fd = open(TARGET_FILE, O_WRONLY | O_CREAT | O_APPEND, 0644);
if(fd < 0){
perror("open() FAIL\n");
goto EXCEPTION;
}
(isNonBlock) ? (operation = LOCK_EX | LOCK_NB)
: (operation = LOCK_EX);
if(flock(fd, operation) < 0){
fprintf(stderr, "flock(%d) FAIL : %s\n", operation, strerror(errno));
goto EXCEPTION;
}
printf("Press enter!\n");
getc(stdin);
write(fd, str, strlen(str));
if(flock(fd, LOCK_UN) < 0){
perror("<<WARNING>> flock(LOCK_UN) FAIL\n");
}
close(fd);
return;
EXCEPTION:
if(isFdOpened(fd)) close(fd);
return;
}
static void dump_file(bool isNonBlock)
{
#define MAX_STR_LEN 128
int fd = -1, operation, maxStrIdx = MAX_STR_LEN - 1, cnt;
char buf[MAX_STR_LEN];
fd = open(TARGET_FILE, O_RDONLY | O_CREAT, 0644);
if(fd < 0){
perror("open() FAIL\n");
goto EXCEPTION;
}
(isNonBlock) ? (operation = LOCK_SH | LOCK_NB)
: (operation = LOCK_SH);
if(flock(fd, operation) < 0){
fprintf(stderr, "flock(%d) FAIL : %s\n", operation, strerror(errno));
goto EXCEPTION;
}
printf("Press enter!\n");
getc(stdin);
cnt = read(fd, buf, maxStrIdx);
buf[cnt] = 0;
if(flock(fd, LOCK_UN) < 0){
perror("flock(LOCK_UN) FAIL\n");
goto EXCEPTION;
}
puts(buf);
close(fd);
return;
EXCEPTION:
if(isFdOpened(fd)) close(fd);
return;
}
static void diplay_usage(const char * const binName)
{
printf("Usage: %s w|r [nb]\n", binName);
}
int main(int argc, char **argv)
{
if( (argc < 2) || (3 < argc) ){
diplay_usage(argv[0]);
goto EXCEPTION;
}
bool nb = false;
if(argc == 3) nb = isNonBlock(argv[2]);
if(isSameStr(argv[1], "w")){
write_file(nb);
}
else if(isSameStr(argv[1], "r")){
dump_file(nb);
}
else {
diplay_usage(argv[0]);
goto EXCEPTION;
}
return 0;
EXCEPTION:
return -1;
}