1 분 소요

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 종류

  1. F_DUPFD
    • fd를 복사하기 위해서 사용
    • 새로운 fd를 반환값으로 돌려줌, 이때 close-on-exec는 공유하지 않음
  2. F_DUPFD_CLOEXEC
    • fd를 복사하고 새로운 fd에 관련된 FD_CLOEXEC를 설정, 새로운 fd가 반환됨
  3. F_GETFD
    • 리턴 값으로 fd에 대한 flag 값(FD_CLOEXEC)을 넘겨줌
  4. F_SETFD
    • FD_CLOEXEC의 값을 지정된 비트값으로 설정
  5. F_GETFL
    • fd에 대한 파일 상태 속성들의 반환값을 돌려줌
    • O_RDONLY, O_WRONLY, O_RDWR, O_EXEC, O_SEARCH 는 개별적으로 판정할 수 없고, ACCMODE라는 마스크를 이용하여 알아 냄
  6. F_SETFL
    • 파일 상태 속성들을 세번째 인수(arg)로 받아 설정
    • O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, O_NONBLOCK
  7. F_GETOWN
    • 비동기 입출력과 관련되어 사용되며, SIGIO와 SIGURG 신호를 받는 프로세스 id를 얻기 위해 사용
  8. 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를 작동하도록 가능

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 :
}

참고

reakwon
joinc


This is personal diary for study documents.
Please comment if I'm wrong or missing something else 😄. 

Top

댓글남기기