파일 디스크립터(File Descriptor)는 Linux or Unix쪽의 시스템에서 Process -> File을 핸들링 시 사용하는 개념으로, Process -> File에 접근시 사용하는 추상적인 값
이다.
파일 디스크립터는 일반적으로 0이 아닌 정수값을 갖게된다.
주로 유닉스 시스템에서는 모든 것을 파일이라고 한다. 정규파일, 디렉토리, 소켓, 파이프, 블록 디바이스, 캐릭터 디바이스 등 모든 객체들을 파일로 관리한다. 유닉스 시스템에서 프로세스가 이 파일들을 접근할 때 파일 디스크립터라는 개념을 이용합니다.
Process가 실행중에 파일을 열게되면 커널은 해당 프로세스의 파일 디스크립터 숫자 중 사용하지 않는 가장 작은 값을 할당해줍니다. 그 다음 프로세스가 열려있는 파일에 시스템 콜을 이용해서 접근할 때, 파일 디스크립터(FD)값을 이용해서 파일을 지칭합니다..
프로그램이 프로세스로 메모리에서 실행될 때, 기본적으로 할당되는 파일디스크립터는 표준입력(Standard Input), 표준 출력(Standard Output), 표준에러(Standard Error)이며 이들에게 각각 0, 1, 2라는 정수가 할당 됩니다.
root@bcs-KVM:~# ps -ef | grep docker
root 875625 1016546 0 5월06 ? 00:01:07 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 1514 -container-ip 172.18.0.2 -container-port 10514
root 876333 1016546 0 5월06 ? 00:00:02 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 443 -container-ip 172.18.0.10 -container-port 8443
root 876340 1016546 0 5월06 ? 00:00:02 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 443 -container-ip 172.18.0.10 -container-port 8443
root 876371 1016546 0 5월06 ? 00:00:02 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 55555 -container-ip 172.18.0.10 -container-port 8080
root 876377 1016546 0 5월06 ? 00:00:02 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 55555 -container-ip 172.18.0.10 -container-port 8080
root 1016546 1 0 4월29 ? 02:28:58 /usr/bin/dockerd -H fd:// -H=tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock
root 1017014 1016546 0 4월29 ? 00:03:31 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -container-ip 172.17.0.5 -container-port 3306
root 1017040 1016546 0 4월29 ? 00:00:04 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 3306 -container-ip 172.17.0.5 -container-port 3306
root 1055180 1016546 0 4월29 ? 00:00:04 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 9090 -container-ip 172.17.0.6 -container-port 9000
root@bcs-KVM:~# ls -trn /proc/875625/fd
total 0
lr-x------ 1 0 0 64 5월 16 11:13 9 -> 'pipe:[112797508]'
l-wx------ 1 0 0 64 5월 16 11:13 8 -> 'pipe:[112797301]'
lr-x------ 1 0 0 64 5월 16 11:13 7 -> 'pipe:[112797301]'
lrwx------ 1 0 0 64 5월 16 11:13 6 -> 'anon_inode:[eventpoll]'
l-wx------ 1 0 0 64 5월 16 11:13 54 -> 'pipe:[112798528]'
lr-x------ 1 0 0 64 5월 16 11:13 53 -> 'pipe:[112798528]'
l-wx------ 1 0 0 64 5월 16 11:13 52 -> 'pipe:[112798527]'
lr-x------ 1 0 0 64 5월 16 11:13 51 -> 'pipe:[112798527]'
lrwx------ 1 0 0 64 5월 16 11:13 50 -> 'socket:[112798526]'
lrwx------ 1 0 0 64 5월 16 11:13 5 -> 'socket:[112798829]'
lrwx------ 1 0 0 64 5월 16 11:13 49 -> 'socket:[112798524]'
l-wx------ 1 0 0 64 5월 16 11:13 48 -> 'pipe:[112798468]'
lr-x------ 1 0 0 64 5월 16 11:13 47 -> 'pipe:[112798468]'
l-wx------ 1 0 0 64 5월 16 11:13 46 -> 'pipe:[112798467]'
lr-x------ 1 0 0 64 5월 16 11:13 45 -> 'pipe:[112798467]'
lrwx------ 1 0 0 64 5월 16 11:13 44 -> 'socket:[112801181]'
lrwx------ 1 0 0 64 5월 16 11:13 43 -> 'socket:[112801179]'
l-wx------ 1 0 0 64 5월 16 11:13 42 -> 'pipe:[112800551]'
lr-x------ 1 0 0 64 5월 16 11:13 41 -> 'pipe:[112800551]'
l-wx------ 1 0 0 64 5월 16 11:13 40 -> 'pipe:[112801148]'
lrwx------ 1 0 0 64 5월 16 11:13 4 -> 'socket:[112797300]'
lr-x------ 1 0 0 64 5월 16 11:13 39 -> 'pipe:[112801148]'
lrwx------ 1 0 0 64 5월 16 11:13 38 -> 'socket:[112800550]'
lrwx------ 1 0 0 64 5월 16 11:13 37 -> 'socket:[112800548]'
l-wx------ 1 0 0 64 5월 16 11:13 36 -> 'pipe:[112798875]'
lr-x------ 1 0 0 64 5월 16 11:13 35 -> 'pipe:[112798875]'
l-wx------ 1 0 0 64 5월 16 11:13 34 -> 'pipe:[112798874]'
lr-x------ 1 0 0 64 5월 16 11:13 33 -> 'pipe:[112798874]'
lrwx------ 1 0 0 64 5월 16 11:13 32 -> 'socket:[112800797]'
lrwx------ 1 0 0 64 5월 16 11:13 31 -> 'socket:[112800795]'
l-wx------ 1 0 0 64 5월 16 11:13 30 -> 'pipe:[112797696]'
lrwx------ 1 0 0 64 5월 16 11:13 3 -> 'socket:[112798826]'
lr-x------ 1 0 0 64 5월 16 11:13 29 -> 'pipe:[112797696]'
l-wx------ 1 0 0 64 5월 16 11:13 28 -> 'pipe:[112797695]'
lr-x------ 1 0 0 64 5월 16 11:13 27 -> 'pipe:[112797695]'
lrwx------ 1 0 0 64 5월 16 11:13 26 -> 'socket:[112797694]'
lrwx------ 1 0 0 64 5월 16 11:13 25 -> 'socket:[112797692]'
l-wx------ 1 0 0 64 5월 16 11:13 24 -> 'pipe:[112797576]'
lr-x------ 1 0 0 64 5월 16 11:13 23 -> 'pipe:[112797576]'
l-wx------ 1 0 0 64 5월 16 11:13 22 -> 'pipe:[112797575]'
lr-x------ 1 0 0 64 5월 16 11:13 21 -> 'pipe:[112797575]'
lrwx------ 1 0 0 64 5월 16 11:13 20 -> 'socket:[112797574]'
l-wx------ 1 0 0 64 5월 16 11:13 2 -> /dev/null
lrwx------ 1 0 0 64 5월 16 11:13 19 -> 'socket:[112797572]'
l-wx------ 1 0 0 64 5월 16 11:13 18 -> 'pipe:[112797571]'
lr-x------ 1 0 0 64 5월 16 11:13 17 -> 'pipe:[112797571]'
l-wx------ 1 0 0 64 5월 16 11:13 16 -> 'pipe:[112797570]'
lr-x------ 1 0 0 64 5월 16 11:13 15 -> 'pipe:[112797570]'
lrwx------ 1 0 0 64 5월 16 11:13 14 -> 'socket:[112797569]'
lrwx------ 1 0 0 64 5월 16 11:13 13 -> 'socket:[112797567]'
l-wx------ 1 0 0 64 5월 16 11:13 12 -> 'pipe:[112797509]'
lr-x------ 1 0 0 64 5월 16 11:13 11 -> 'pipe:[112797509]'
l-wx------ 1 0 0 64 5월 16 11:13 10 -> 'pipe:[112797508]'
l-wx------ 1 0 0 64 5월 16 11:13 1 -> /dev/null
lr-x------ 1 0 0 64 5월 16 11:13 0 -> /dev/null
root@bcs-KVM:~#
참고
- 프로그램이 프로세스로 메모리에서 실행을 시작 할 떄, 기본적으로 할당되는 파일 디스크립터들이 있다.
- 바로 표준 입력, 표준 출력, 표준 에러이다. 이들에게 각각 0,1,2라는 정수가 할당되며, 이 매크로는 <unitsh.h> 헤더에서 찾아 볼 수있다.
- 0이 아닌 정수로 표현되는 파일 디스크립터는 0~ OPEN_MAX까지 값을 가진다.
정리하자면 파일 디스크립터는 파이프, FIFO, 소켓, 터미널, 디바이스, 일반파일 등 종류에 상관없이 모든 열려있는 파일을 참조할때 쓴다.
파일 디스크립터 | 목적 | POSIX 이름 | stdio 스트림 |
---|---|---|---|
0 | 표준입력 | STDIN_FILENO | stdin |
1 | 표준출력 | STDOUT_FILENO | stdout |
2 | 표준에러 | STDERR_FILENO | stderr |
파일 디스크립터와 열려 있는 파일의 관계
- 각 프로세스별로 커널은 open file descriptor table 을 갖고 있다. 테이블의 각 엔트리는 하나의 파일 디스크립터에 대한 동작 제어 플래그, 열린 파일을 가리키는 참조를 담고 있다
- open file description은 현재 파일의 offset, flag, 접근 모드, i/o 관련 설정, 파일의 i-node 객체를 가리키는 레퍼런스를 갖고 있다.
- i-node는 파일 종류 (일반파일, 소켓, fifo)와 권한, lock 목록 포인터, 여러 파일 오퍼레이션과 다양한 파일 속성(크기, 타임스탬프등)을 갖고 있다.
- 만약 같은 open file description을 가리키는 2개의 fd는 offset값을 공유 한다.