유닉스 시스템에서는 일반적인 파일, 디렉토리, 소켓 등등 모든 객체들을 파일로써 관리한다. 유닉스 시스템에서 이러한 파일들을 접근 할 때에 파일 디스크립터라는 개념을 이용한다.
응용 프로세스가 파일을 열거나 생성 하게 되면 정수로된 파일 디스크립터를 얻게 되는데 이 정수는 읽기(read함수), 쓰기(write함수), 닫기(close함수)등의 동작에서 그 파일을 가리키는데 사용된다.
기본적으로 할당되는 파일 디스크립터 ( 0 (표준 입력), 1 (표준 출력), 2 (표준 에러) )는 unistd.h에 메크로로 정의 되어 있고, 우리가 생성하는 파일 디스크립터는 3번부터 차례대로 할당을 받는다.
파일을 열고, 읽고, 쓰고, 위치를 변경하고, 파일을 닫는 등의 파일 입출력 작업을 수행하는 함수들을 파일 입출력 함수 또는 파일 디스크립터 함수라고 한다. 파일 입출력 함수들은 시스템 콜(System Call)을 호출하여 파일 디스크립터를 이용해 파일과 상호작용 한다.
Linux, Unix 계열의 시스템에서 Process(프로세스)가 File(파일)을 열 때 open 함수를 사용 할 수 있다. 파일 디스크립터를 리턴하는 open함수의 프로토 타입은 다음과 같다.
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
첫 번째 프로토 타입은 파일경로(pathname
)과 파일 열기 모드(flags
)를 인자로 받고, 두 번쨰 프로토타입은 추가로 파일 권한도 인자로 받는다.
open함수는 파일 디스크립터를 반환값으로 가지며, 파일을 열지 못할 경우 ‘-1’을 반환한다.
O_RDONLY
Necessary
파일을 읽기 전용으로 연다. (Read Only)
O_WRONLY
Necessary
파일을 쓰기 전용으로 연다. (Write Only)
O_RDWR
Necessary
파일을 쓰기와 읽기용으로 연다. (Read & Write)
O_EXEC
Necessary
파일을 실행 전용으로 연다. (Execute Only)
O_SEARCH
Necessary
디렉토리 파일을 탐색 전용으로 연다. (Search Only)
read함수는 파일 디스크립터에 해당하는 파일에서 데이터를 읽어서 버퍼에 저장한다. read함수의 프로토타입은 다음과 같다.
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
첫번째 인자인 fd는 읽을 파일의 파일 디스크립터이다. 두 번째 인자인 buf는 읽은 데이터를 저장할 버퍼이고, 세 번째 인자인 count는 읽을 최대 바이트 수를 받는 인자이다.
read함수는 성공적으로 읽은 데이터의 크기를 ssize_t 타입으로 반환하며 에러 발생 시 ‘-1’을 반환한다.
대표적으로 에러가 발생 할 수 있는 상황은 다음과 같다.
read함수는 파일의 끝에 도달하거나, 읽기 작업이 완료되면 ‘0’을 반환한다.
write함수는 파일 디스크립터에 해당하는 파일에 데이터를 쓴다. write함수의 프로토타입은 다음과 같다.
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
첫번째 인자인 fd는 쓸 파일의 파일 디스크립터이다. 두 번째 인자인 buf는 쓸 데이터가 저장된 버퍼이고, 세 번째 인자인 count는 쓸 바이트 수를 받는 인자이다.
write함수는 성공적으로 쓴 바이트 수를 ssize_t 타입으로 반환하고, 에러 발생 시 -1을 반환한다.
ssize_t 타입은 부호 있는 정수형 데이터 타입으로 시스템 아키텍처에 따라 크기가 다르다. 예를 들어 32비트 아키텍처에서는 4바이트이고, 64비트 아키텍처에서는 8바이트이다.