[CS] 파일 디스크립터 (file descriptor)

파일 디스크립터(file descriptor)란, 운영체제에서 열린 파일이나 입출력 리소스를 식별하기 위한 정수형 식별자이다. 주로 유닉스 계열 시스템(Linux 포함)에서 사용되며, 커널이 열려 있는 파일(혹은 소켓, 파이프 등)을 추적하고 관리할 수 있도록 도와준다.


1. 파일 디스크립터의 기본 개념

  • 프로세스가 open() 시스템 호출을 통해 파일을 열면, 커널은 파일에 대한 정보를 저장하고, 그에 대응하는 정수값(fd)을 반환한다.
  • 이 정수값을 통해 프로세스는 이후 read(), write(), close() 등의 시스템 호출에서 파일에 접근할 수 있다.

2. 기본 파일 디스크립터 (표준 입출력)

이름 번호 설명
stdin 0 표준 입력 (keyboard)
stdout 1 표준 출력 (screen)
stderr 2 표준 오류 출력

이들은 프로그램이 시작할 때 자동으로 열려 있으며, 이를 리디렉션 하거나 대체할 수 있다.


3. 사용 예시

#include <fcntl.h>
#include <unistd.h>

int fd = open("example.txt", O_RDONLY);
if (fd < 0) {
    perror("open failed");
} else {
    char buf[100];
    read(fd, buf, sizeof(buf)); // 파일 디스크립터를 이용한 읽기
    close(fd);
}
  • open()은 파일을 열고, 파일 디스크립터 fd를 반환한다.
  • read()와 close()는 이 fd를 사용하여 작업한다.

4. 특징 및 활용

  • 단순한 정수지만, 내부적으로는 커널의 파일 테이블(file table)과 연결되어 있다.
  • 디스크 파일 외에도, 소켓(socket), 파이프(pipe), 디바이스(device) 등 다양한 리소스에도 적용된다.
  • dup(), dup2() 등을 이용해 파일 디스크립터를 복제하거나 리디렉션할 수 있다.

5. 예: 리디렉션

int fd = open("log.txt", O_WRONLY | O_CREAT, 0644);
dup2(fd, 1); // stdout을 log.txt로 변경
printf("이 메시지는 log.txt에 출력된다.\n");

6. 활용 예시

파일 디스크립터를 리디렉션할 수 있다는 것을 이용해 로그 파일에 출력을 하도록 구성할 수 있다.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("log.txt", O_WRONLY | O_CREAT | O_APPEND, 0644);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    // 표준 출력(stdout)을 log.txt로 변경
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);  // 에러도 로그 파일에 저장하고 싶다면

    // 이제부터 printf는 log.txt에 기록된다
    printf("프로그램이 시작되었습니다.\n");
    fprintf(stderr, "경고: 설정 파일이 없습니다.\n");

    close(fd);
    return 0;
}

설명

  • open()은 로그 파일을 열고 파일 디스크립터 fd를 얻는다.
  • dup2(fd, 1)은 표준 출력(1번)을 fd로 바꾼다. 이후 printf()는 stdout을 통해 로그 파일로 출력된다.
  • O_APPEND는 로그가 기존 파일에 이어 붙여지도록 한다.
  • O_CREAT은 로그 파일이 없을 경우 새로 만든다.
  • 0644는 파일 권한을 의미한다 (rw-r--r--).

추가 활용 예시

  • 디버깅용 로그: 프로그램이 백그라운드에서 실행될 때도 로그를 파일로 남길 수 있다.
  • 서버 로그: stdout, stderr을 로그 파일로 리디렉션하여 운영 중 로그를 저장.
  • 로그 회전(log rotation)을 위해 주기적으로 close() 후 새 파일로 open().