Search
Duplicate

20210126(화)

내용
42) 파일 디스크럽터
공부장소
2021/03/20 18:22

파일 디스크립터란?

시스템으로부터 할당 받은 파일을 대표하는 음수가 아닌 0과 양수인 정수 값(Non-negative Integer)
프로세스에서 열린 파일의 목록을 관리하는 테이블의 인덱스
흔히 유닉스 시스템에서 모든 것은 파일이라고 한다. 일반적인 정규파일(Regular File)에서부터 디렉토리(Directory), 소켓(Socket), 파이프(PIPE), 블록 디바이스, 캐릭터 디바이스 등등 모든 객체들은 파일로써 관리된다. 유닉스 시스템에서 프로세스가 이 파일들을 접근할 때에 파일 디스크립터(File Descriptor)라는 개념을 이용한다.
응용 프로세스가 파일을 열거나 생성 하게 되면 정수로 된 파일 디스크립터를 얻게 되는데 이 파일 디스크립터는 이후에 일어나는 모든 파일 동작 즉, 읽기(read()), 쓰기(write()), 파일 동작제어(fcntl()), 파일 닫기(close())등의 동작에서 그 파일을 가리키는데 사용된다. 0, 1, 2는 프로세스가 메모리에서 실행을 시작할때 기본적으로 할당되는 파일 디스크립터이다.

기본적으로 할당되는 파일 디스크립터

0 : 표준 입력(Standard Input) / STDIN_FILENO
1 : 표준 출력(Standard Output) / STDOUT_FILENO
2 : 표준 에러(Standard Error) / STDERR_FILENO
그러므로 우리가 생성하는 파일 디스크립터들은 3번부터 차례대로 할당받게 된다.
쉽게 생각하면, 파일 디스크립터는 파일을 다루기 위해서 해당파일의 주소를 참조하여 접근하는 형태라고 생각하면 된다.

파일 디스크립터를 확인해보자

우선 파일 디스크립터를 확인하기 전에 필요한 함수를 살펴보자.
open(pathname, flags, mode) //return fd
C
복사
open함수는 pathname이 가리키는 파일을 열고 열린 파일을 이후 호출에서 참조할 때 사용하는 파일 디스크립터를 리턴한다.(현재 가용한 숫자 중 가장 작은 값으로!)
1.
파일 디스크립터 확인
file.c 파일과 test.txt파일을 생성한 후 프로세스가 파일을 열 때 얻는 파일 디스크립터를 출력해보자. test.txt파일은 아무내용이나 넣어도 상관 없다. 아래는 file.c 파일이다.
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> int main(void) { int fd; fd = open("test.txt", O_RDONLY); if (fd < 1) { printf("open() error"); exit(1); } printf("FD : %d\n", fd); close(fd); return (0); }
C
복사
실행 결과
해당 파일을 컴파일한 후 실행해보니 파일 디스크립터가 3부터 부여되는 것을 확인할 수 있다!! 여기서 나오는 숫자 3이 어떤 의미일까? 아래의 그림을 보면 어떻게 정수값으로 된 파일 디스크립터로 원하는 파일에 접근하는지 쉽게 이해할 수 있다.
파일 디스크립터의 값, 즉 fd는 프로세스가 유지하고 있는 FD Table의 index이다. 위의 예제에서 우리는 3이라는 숫자가 나왔다. 그림에서 보듯이 우리는 이 숫자 3을 사용해서 FD Table의 3번째 인덱스로 접근하고, 해당 칸이 가리키는 파일로 가서 원하는 행동을 할 수 있는 것이다.
FD Table의 각 칸들은 FD Flag와 File Table Pointer를 가지고 있다.
File Table의 각 칸들은 mode와 inode Table Pointer의 Offset을 가지고 있다.
inode Table은 소유자 그룹, 접근 모드(읽기, 쓰기, 실행 권한), 파일 형태, 아이노드 숫자(inode number, i-number) 등 해당 파일에 관한 정보를 가지고 있다.
inode란 무엇일까!? 파일을 기술하는 디스크 상의 데이터 구조로서 파일의 데이터 블록이 디스크 상의 어느 주소에 위치하고 있는가와 같은 파일에 대한 중요한 정보를 갖고 있다. 각각의 inode들은 고유번호(inode number)를 가지고 있어서 파일을 식별할때 사용한다. 터미널에서 ls -i 옵션으로 inode number를 확인할 수 있다.
그렇다면, 이렇게 생생된 파일 디스크립터를 변경하는 것도 가능할까?
2.
기존 파일디스크립터를 복제
파일 디스크립터를 변경시킬 수 있는지 확인하기 위해서 기존에 사용중인 파일 디스크립터 번호를 복제해 볼 계획이다.
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> int main(void) { int fd; int fd2; fd = open("test.txt", O_RDONLY); fd2 = open("test.txt", O_RDONLY); if (fd < 1 || fd2 < 1) { printf("open() error"); exit(1); } printf("fd\t: %d\n", fd); printf("fd2\t: %d\n", fd2); printf("fd2 = dup(fd)\n"); fd2 = dup(fd); printf("fd\t: %d\n", fd); printf("fd2\t: %d\n", fd2); close(fd); close(fd2); return (0); }
C
복사
실행 결과
기존 fd는 3을, fd2는 4를 할당받았다. 이후 dup()함수를 활용해서 fd를 복사해서 fd2에 넣었더니 fd2가 5가 되었다. 이것은 3이 이미 사용중인 파일 디스크럽터이고 4도 지금 현재 fd2에서 사용중이므로 5번이 새로 할당된 것이다. 즉 dup()를 통해서 복제를 하면 새로운 파일 디스크립터를 생성한다고 생각하면 된다.
<출처>