리눅스 시스템 및 네트워크 프로그래밍/시스템 프로그래밍

파일 디스크립터와 입출력 시스템 콜

ROBL 2025. 2. 3.
728x90
반응형

리눅스에서 파일, 소켓, 파이프 등 다양한 리소스를 다룰 때 파일 디스크립터(File Descriptor, FD) 개념을 이해하는 것이 중요합니다. 파일 디스크립터는 운영체제가 프로세스와 리소스를 연결하는 핵심 구조이며, 이를 통해 입출력 시스템 콜을 효율적으로 활용할 수 있습니다.

이번 글에서는 파일 디스크립터의 개념을 설명하고, 리눅스에서 제공하는 주요 입출력 시스템 콜(open, read, write, close, lseek 등)의 동작 원리와 사용법을 살펴보겠습니다.


1. 파일 디스크립터란?

파일 디스크립터(File Descriptor, FD)는 리눅스 운영체제가 열려 있는 파일이나 소켓 등을 식별하기 위해 프로세스에 할당하는 정수 값입니다. 모든 프로세스는 파일 디스크립터를 통해 리소스에 접근합니다.

1.1 파일 디스크립터의 기본 값

리눅스에서 일반적으로 다음과 같이 표준 파일 디스크립터가 할당됩니다.

파일 디스크립터 의미 매크로
0 표준 입력 STDIN_FILENO
1 표준 출력 STDOUT_FILENO
2 표준 에러 STDERR_FILENO

사용자가 파일을 열거나 소켓을 생성하면 3 이상의 정수 값이 파일 디스크립터로 할당됩니다.


2. 입출력 시스템 콜

파일 디스크립터를 활용하는 대표적인 입출력 시스템 콜은 다음과 같습니다.

2.1 open() – 파일 열기

파일을 열어 파일 디스크립터를 반환하는 함수입니다.

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
    perror("open");
}

O_RDONLY는 읽기 전용으로 파일을 여는 옵션이며, open()이 실패하면 -1을 반환합니다.

2.2 read() – 파일에서 데이터 읽기

파일에서 데이터를 읽고 버퍼에 저장하는 시스템 콜입니다.

#include <unistd.h>

char buffer[100];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read == -1) {
    perror("read");
}

read()는 파일의 끝(EOF)에 도달하면 0을 반환하며, 실패 시 -1을 반환합니다.

2.3 write() – 파일에 데이터 쓰기

파일 디스크립터를 통해 데이터를 출력하는 시스템 콜입니다.

#include <unistd.h>

const char *data = "Hello, World!";
ssize_t bytes_written = write(fd, data, strlen(data));
if (bytes_written == -1) {
    perror("write");
}

write()의 반환 값은 실제로 쓰인 바이트 수이며, -1이면 오류를 의미합니다.

2.4 lseek() – 파일 오프셋 변경

파일의 읽기/쓰기 위치를 변경할 때 사용하는 시스템 콜입니다.

#include <unistd.h>

off_t offset = lseek(fd, 10, SEEK_SET);
if (offset == -1) {
    perror("lseek");
}

SEEK_SET은 파일의 시작점을 기준으로 10바이트 이동하는 옵션입니다.

2.5 close() – 파일 닫기

열려 있는 파일 디스크립터를 닫고 리소스를 해제하는 시스템 콜입니다.

#include <unistd.h>

if (close(fd) == -1) {
    perror("close");
}

파일 디스크립터가 닫히면 다른 프로세스가 해당 파일을 사용할 수 있습니다.


3. 파일 디스크립터 활용 사례

3.1 표준 출력 리다이렉션

파일 디스크립터를 조작하면 표준 입출력을 파일로 변경할 수 있습니다.

int fd = open("output.txt", O_WRONLY | O_CREAT, 0644);
dup2(fd, STDOUT_FILENO);
close(fd);

printf("이 내용은 터미널이 아닌 output.txt에 기록됩니다.\n");

위 코드에서 dup2(fd, STDOUT_FILENO)를 사용하여 표준 출력을 파일로 변경했습니다.

3.2 다중 파일 처리

여러 개의 파일을 동시에 열고 관리하는 것도 가능합니다.

int fd1 = open("file1.txt", O_RDONLY);
int fd2 = open("file2.txt", O_RDONLY);

각 파일은 서로 다른 파일 디스크립터를 가지므로 독립적으로 관리할 수 있습니다.


4. 정리

  • 파일 디스크립터는 운영체제가 파일, 소켓 등을 식별하는 정수 값입니다.
  • open(), read(), write(), lseek(), close() 같은 입출력 시스템 콜을 통해 파일을 읽고, 쓰고, 조작할 수 있습니다.
  • 표준 입출력을 파일로 변경하거나, 여러 파일을 동시에 관리하는 고급 활용도 가능합니다.

파일 디스크립터와 시스템 콜을 이해하면 효율적인 파일 I/O 처리를 구현할 수 있습니다. 다음 글에서는 비동기 I/O와 고급 파일 처리 기법을 다루겠습니다.

728x90
반응형

댓글

💲 추천 글