-
Notifications
You must be signed in to change notification settings - Fork 0
Study : CPP : fcntl
| 항목 | 내용 |
|---|---|
| 일자 | 2022.03.29 |
| 작성자 | jwoo |
| 제목 | webserv 허용함수 - fcntl
|
| 한줄요약 | 파일 제어 함수 |
fcntl(fd, F_SETFL, O_NONBLOCK)
NAME
file control
SYNOPSIS
#include <fcntl.h>
int fcntl(int fildes, int cmd, ... /* arg */);DESCRIPTION
fcntl()은 열린 파일 디스크립터 fd, fildes 에서 아래 설명하는 동작들 중 하나를 수행하며, cmd에 따라 동작이 정해진다:
| cmd | arg type | description |
|---|---|---|
| ... | .. | ...... |
| F_SETFL | int | 파일 상태 플래그들을 arg에 지정된 값으로 설정한다. arg에서 파일 접근 모드와 파일 생성 플래그들은 무시한다. 리눅스에서 이 명령은 O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, O_NONBLOCK 플래그만 바꿀 수 있다. O_DSYNC와 O_SYNC 플래그는 바꾸는 게 불가능하다. |
| ... | .. | ...... |
fcntl()은 선택적인 세 번째 인자를 받을 수 있다. 그 인자가 필요한지 여부는 cmd에 따라 정해진다. 대부분의 경우 필요한 타입이 int이며, 인자가 필요치 않으면 void라고 되어 있다.
cmd F_GETFL과 F_SETFL에서 사용할 수 있는 flags는 다음과 같다:
| flag | description |
|---|---|
| O_NONBLOCK | Non-blocking I/O; read(2) 에 사용할 수 있는 데이터가 없거나 write(2) 연산 작업이 차단되면 읽기 또는 쓰기 호출은 EAGAIN 오류와 함께 -1을 반환합니다. |
| O_APPEND | 파일 끝에 쓰기를 합니다. open(2)의 O_APPEND 플래그에 해당합니다. |
| O_ASYNC | I/O가 가능한 경우(예: 읽을 데이터가 있는 경우) SIGIO 신호가 프로세스 그룹으로 전송되도록 합니다. |
RETURN VALUES
성공적으로 완료되면, 반환값은 cmd에 의해 결정된다:
| cmd | return value |
|---|---|
| F_DUPFD | 새 파일 디스크립터. |
| F_GETFD | 파일 디스크립터 플래그 값. |
| F_GETFL | 파일 상태 플래그 값. |
| F_GETOWN | 파일 디스크립터 소유자 값. |
| other | -1이 아닌 값. |
오류 시 -1을 반환하며 오류를 나타내도록 errno를 설정한다.
ERRORS
The fcntl() system call will fail if:
| error | description |
|---|---|
| ... | ...... |
| EACCES or EAGAIN | 다른 프로세스가 잡은 락 때문에 동작을 수행할 수 없다. |
| EAGAIN | 파일을 다른 프로세스가 메모리 매핑했기 때문에 동작을 수행할 수 없다. |
| EBADF | Fildes가 열린 파일 디스크립터가 아니다. |
| ... | ...... |
SEE ALSO
close(2), execve(2), flock(2), getdtablesize(2), open(2), pipe(2), setsockopt(2), socket(2), sigaction(3)
BUGS
| flag | description |
|---|---|
| ... | ...... |
| F_SETFL | F_SETFL로 O_DSYNC나 O_SYNC 플래그의 상태를 바꾸는 게 불가능하다. 그 플래그들의 상태를 바꾸려고 하면 무시된다. |
| ... | ...... |
I/O 는 Input 과 Output 의 약자로, I/O 모델은 파일 입출력과 관련된 모델이다.
I/O 작업은 user 단계에서 수행할 수 없고, kernel 에서만 수행할 수 있다. 그러므로 I/O 작업은 user에서 요청하고, kernel에서 수행한 뒤, user가 응답받는 구조이다. user가 응답을 받을 때까지 대기하고 있는지(Blocking vs Non-blocking), 응답을 어떤 순서로 받는지(Asynchronous vs Synchronous)에 따라 모델의 종류가 갈린다.
-
Blocking I/O
가장 기본적인 I/O 모델로, linux의 소켓통신은 기본적으로 Blocking 방식으로 진행된다.
I/O 작업을 하는 동안 유저는 요청을 날리고 응답을 기다리는 사이에 유저 프로세스를 중단한다. 커널이 작업을 끝내고 응답을 보낼 때까지 유저는 대기상태에 빠지기 때문에 리소스 낭비가 있다.
getchar()함수가 엔터키를 입력받을 때까지 영원히 기다리는 것을 생각하면 Blocking 모델을 좀 더 쉽게 이해할 수 있다.
-
Non-Blocking I/O
Non-Blocking 방식은 Blocking 방식과 달리 유저가 커널의 응답을 대기하고만 있지 않는다. 유저 프로세스가 커널에게 I/O를 작업 요청하는 함수를 호출하면, 유저 프로세스를 중단시키지 않고, 유저가 요청한 즉시 결과를 반환한다.
만약 커널의 작업이 당장 완료될 수 없다면 작업 진행중이란 의미로
EWOULDBLOCK를 리턴하고, 이 결과값을 리턴받은 유저는 다른 프로세스를 진행할 수 있다. 유저는 다른 프로세스 작업을 수행하며, I/O 작업이 완료될때까지 중간중간 시스템 콜을 날려 I/O 작업이 완료됐는지 확인한다.
// uploaded 220329