본문으로 건너뛰기

1. 파일 디스크립터란?

  • 파일 디스크립터(File Descriptor)는 Unix/Linux 시스템에서 프로세스가 파일을 다룰 때 사용하는 추상화된 식별자입니다.
  • 간단히 말해서, 프로세스가 특정 파일에 접근할 때 사용하는 참조 번호라고 생각하면 됩니다.
  • 실제로는 음수가 아닌 정수값(0, 1, 2, ...)으로 표현됩니다.

1.1 기본 개념 이해하기

  • 프로세스가 파일을 열면 운영체제는 해당 파일에 대한 파일 디스크립터를 할당합니다.
  • 이후 프로세스는 이 번호를 통해 파일을 읽거나 쓰는 등의 작업을 수행할 수 있습니다.
  • 파일 디스크립터는 프로세스별로 고유합니다. 즉, 서로 다른 프로세스의 같은 번호는 다른 파일을 가리킬 수 있습니다.

실제 파일 시스템의 파일뿐만 아니라, 파이프, 소켓, 장치 등 모든 입출력 리소스도 파일 디스크립터로 다룰 수 있습니다. 이것이 유닉스의 "모든 것은 파일이다"라는 철학의 실제 구현입니다.

2. 표준 파일 디스크립터

  • 모든 프로세스는 기본적으로 세 개의 표준 파일 디스크립터를 가집니다:
  • 0 (STDIN_FILENO): 표준 입력
    • 기본적으로 키보드 입력을 나타냅니다
    • C의 stdin에 해당
  • 1 (STDOUT_FILENO): 표준 출력
    • 기본적으로 콘솔 화면을 나타냅니다
    • C의 stdout에 해당
  • 2 (STDERR_FILENO): 표준 에러
    • 에러 메시지 출력을 위한 스트림입니다
    • C의 stderr에 해당

3. 파일 디스크립터의 동작 방식

3.1 내부 구조

파일 디스크립터는 세 개의 테이블을 통해 실제 파일과 연결됩니다:

  1. 프로세스별 파일 디스크립터 테이블
    • 각 프로세스가 가지고 있는 테이블
    • 파일 디스크립터 번호와 파일 테이블 엔트리를 매핑
  2. 시스템 전체 파일 테이블
    • 모든 프로세스가 공유하는 테이블
    • 파일의 오프셋, 접근 모드 등의 정보 포함
  3. inode 테이블
    • 실제 파일의 메타데이터를 포함
    • 파일 권한, 크기, 위치 등의 정보 저장

3.2 주요 연산

파일 디스크립터로 수행할 수 있는 주요 작업들:

  • 파일 읽기/쓰기: read(), write()
  • 파일 위치 이동: lseek()
  • 파일 정보 얻기: fstat()
  • 파일 디스크립터 복제: dup(), dup2()
  • 파일 닫기: close()
경고

열린 파일 디스크립터는 반드시 닫아주어야 합니다. 그렇지 않으면 파일 디스크립터 누수가 발생할 수 있습니다.

4. 실제 사용 예시

4.1 기본적인 파일 조작

// 파일 열기
int fd = open("example.txt", O_RDWR);
if (fd == -1) {
perror("파일 열기 실패");
return 1;
}

// 파일에 데이터 쓰기
write(fd, "Hello, World!\n", 13);

// 파일 포인터를 시작으로 이동
lseek(fd, 0, SEEK_SET);

// 데이터 읽기
char buffer[100];
read(fd, buffer, 100);

// 파일 디스크립터 닫기
close(fd);

4.2 파일 디스크립터 복제

// 표준 출력을 파일로 리다이렉션
int fd = open("output.txt", O_WRONLY | O_CREAT, 0644);
dup2(fd, STDOUT_FILENO);
printf("이 내용은 output.txt에 저장됩니다\n");

5. 파일 디스크립터 활용 팁

5.1 효율적인 사용

  • 필요한 파일 디스크립터만 열어두기
  • 사용이 끝난 파일 디스크립터는 즉시 닫기
  • 파일 디스크립터 한계값 확인하기
ulimit -n  # 프로세스당 최대 파일 디스크립터 수 확인

5.2 일반적인 실수 방지

  • 파일 디스크립터 누수 방지
  • 중복 닫기 오류 피하기
  • 올바른 에러 처리하기
위험

이미 닫은 파일 디스크립터를 다시 사용하려고 하면 예기치 않은 동작이 발생할 수 있습니다.

6. 마치며

  • 파일 디스크립터는 Unix/Linux 시스템에서 파일과 I/O를 다루는 근간이 되는 개념입니다.
  • 단순한 정수값으로 보이지만, 이를 통해 운영체제는 효율적으로 파일 접근을 관리하고 프로세스 간의 자원 공유를 가능하게 합니다.