[Linux] fcntl 함수
1. fcntl이란?
- 이미 열려있는 파일의 특성 제어를 위해서 사용
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
- 첫번째 인자로 주어지는 fd는 open(), socket() 등의 시스템 호출을 통해서 만들어진 파일지정자
- 두번째 인자인 cmd가 fd에 대한 특성을 제어하기 위한 값
2. 특성 제어를 위한 cmd 종류
- F_DUPFD
- fd를 복사하기 위해서 사용
- 새로운 fd를 반환값으로 돌려줌, 이때 close-on-exec는 공유하지 않음
- F_DUPFD_CLOEXEC
- fd를 복사하고 새로운 fd에 관련된 FD_CLOEXEC를 설정, 새로운 fd가 반환됨
- F_GETFD
- 리턴 값으로 fd에 대한 flag 값(FD_CLOEXEC)을 넘겨줌
- F_SETFD
- FD_CLOEXEC의 값을 지정된 비트값으로 설정
- F_GETFL
- fd에 대한 파일 상태 속성들의 반환값을 돌려줌
- O_RDONLY, O_WRONLY, O_RDWR, O_EXEC, O_SEARCH 는 개별적으로 판정할 수 없고, ACCMODE라는 마스크를 이용하여 알아 냄
- F_SETFL
- 파일 상태 속성들을 세번째 인수(arg)로 받아 설정
- O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, O_NONBLOCK
- F_GETOWN
- 비동기 입출력과 관련되어 사용되며, SIGIO와 SIGURG 신호를 받는 프로세스 id를 얻기 위해 사용
- F_SETOWN
- 비동기 입출력과 관련되어 사용되며, SIGIO와 SIGURG 신호를 수신하는 프로세스 ID를 설정하기 위해 사용
- close-on-exec 란?
- open-on-exec :
- 보통 프로세스에서 exec()를 시켜서 새로운 프로세스를 실행시키면 기존의 프로세스 이미지를 덮어쓰게 됨
- 또한, 특별한 설정이 없을 경우 열린 fd를 그대로 넘겨줌
- close-on-exec :
- exec를 이용해서 프로세스를 만들기 전에 기존에 열린 fd들을 정리하고 싶을 때가 있는 경우를 close-on-exec 시킨다고 말함
- fcntl을 이용해서 열린 fd에 대해서 close-on-exec를 작동하도록 가능
- open-on-exec :
3. 속성 조회, 변경
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
void printAccessMode(int flags){
switch(flags & O_ACCMODE){
case O_RDONLY:
printf("RDONLY\n");
break;
case O_WRONLY:
printf("WRONLY\n");
break;
case O_RDWR:
printf("RDWR\n");
break;
}
printf("append %s \n", (flags & O_APPEND) ? "O":"X");
printf("nonblocking %s \n", (flags & O_NONBLOCK) ? "O":"X");
printf("\n");
}
int main(){
int fd = open("test.txt", O_RDONLY|O_CREAT, 0666);
int flags = fcntl(fd, F_GETFL, 0);
printAccessMode(flags);
// O_APPEND flag 추가
flags |= O_APPEND;
// F_SETFL with arg
fcntl(fd, F_SETFL, flags);
flags = fcntl(fd, F_GETFL, 0);
printAccessMode(flags);
}
4. 비동기 예제
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
int main(){
char buf[128] = {0,};
int fd = 0;
int flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
read(fd, buf, sizeof(buf));
// 사용자 입력을 기다리지 않고 바로 버퍼를 출력하고 끝냄
printf("buf : %s \n", buf); // buf :
}
참고
This is personal diary for study documents.
Please comment if I'm wrong or missing something else 😄.
댓글남기기