File Descriptor

Hyeseong·2022년 5월 16일
0

Concept

파일 디스크립터(File Descriptor)는 Linux or Unix쪽의 시스템에서 Process -> File을 핸들링 시 사용하는 개념으로, Process -> File에 접근시 사용하는 추상적인 값이다.

파일 디스크립터는 일반적으로 0이 아닌 정수값을 갖게된다.

주로 유닉스 시스템에서는 모든 것을 파일이라고 한다. 정규파일, 디렉토리, 소켓, 파이프, 블록 디바이스, 캐릭터 디바이스 등 모든 객체들을 파일로 관리한다. 유닉스 시스템에서 프로세스가 이 파일들을 접근할 때 파일 디스크립터라는 개념을 이용합니다.

Process가 실행중에 파일을 열게되면 커널은 해당 프로세스의 파일 디스크립터 숫자 중 사용하지 않는 가장 작은 값을 할당해줍니다. 그 다음 프로세스가 열려있는 파일에 시스템 콜을 이용해서 접근할 때, 파일 디스크립터(FD)값을 이용해서 파일을 지칭합니다..

프로그램이 프로세스로 메모리에서 실행될 때, 기본적으로 할당되는 파일디스크립터는 표준입력(Standard Input), 표준 출력(Standard Output), 표준에러(Standard Error)이며 이들에게 각각 0, 1, 2라는 정수가 할당 됩니다.

File Descriptor 확인 방법

실행중인 프로세스 PID 확인

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

PID로 해당 프로세스의 File Descriptor 정보 확인

root@bcs-KVM:~# ls -trn /proc/875625/fd
total 0
lr-x------ 1 0 0 64  516 11:13 9 -> 'pipe:[112797508]'
l-wx------ 1 0 0 64  516 11:13 8 -> 'pipe:[112797301]'
lr-x------ 1 0 0 64  516 11:13 7 -> 'pipe:[112797301]'
lrwx------ 1 0 0 64  516 11:13 6 -> 'anon_inode:[eventpoll]'
l-wx------ 1 0 0 64  516 11:13 54 -> 'pipe:[112798528]'
lr-x------ 1 0 0 64  516 11:13 53 -> 'pipe:[112798528]'
l-wx------ 1 0 0 64  516 11:13 52 -> 'pipe:[112798527]'
lr-x------ 1 0 0 64  516 11:13 51 -> 'pipe:[112798527]'
lrwx------ 1 0 0 64  516 11:13 50 -> 'socket:[112798526]'
lrwx------ 1 0 0 64  516 11:13 5 -> 'socket:[112798829]'
lrwx------ 1 0 0 64  516 11:13 49 -> 'socket:[112798524]'
l-wx------ 1 0 0 64  516 11:13 48 -> 'pipe:[112798468]'
lr-x------ 1 0 0 64  516 11:13 47 -> 'pipe:[112798468]'
l-wx------ 1 0 0 64  516 11:13 46 -> 'pipe:[112798467]'
lr-x------ 1 0 0 64  516 11:13 45 -> 'pipe:[112798467]'
lrwx------ 1 0 0 64  516 11:13 44 -> 'socket:[112801181]'
lrwx------ 1 0 0 64  516 11:13 43 -> 'socket:[112801179]'
l-wx------ 1 0 0 64  516 11:13 42 -> 'pipe:[112800551]'
lr-x------ 1 0 0 64  516 11:13 41 -> 'pipe:[112800551]'
l-wx------ 1 0 0 64  516 11:13 40 -> 'pipe:[112801148]'
lrwx------ 1 0 0 64  516 11:13 4 -> 'socket:[112797300]'
lr-x------ 1 0 0 64  516 11:13 39 -> 'pipe:[112801148]'
lrwx------ 1 0 0 64  516 11:13 38 -> 'socket:[112800550]'
lrwx------ 1 0 0 64  516 11:13 37 -> 'socket:[112800548]'
l-wx------ 1 0 0 64  516 11:13 36 -> 'pipe:[112798875]'
lr-x------ 1 0 0 64  516 11:13 35 -> 'pipe:[112798875]'
l-wx------ 1 0 0 64  516 11:13 34 -> 'pipe:[112798874]'
lr-x------ 1 0 0 64  516 11:13 33 -> 'pipe:[112798874]'
lrwx------ 1 0 0 64  516 11:13 32 -> 'socket:[112800797]'
lrwx------ 1 0 0 64  516 11:13 31 -> 'socket:[112800795]'
l-wx------ 1 0 0 64  516 11:13 30 -> 'pipe:[112797696]'
lrwx------ 1 0 0 64  516 11:13 3 -> 'socket:[112798826]'
lr-x------ 1 0 0 64  516 11:13 29 -> 'pipe:[112797696]'
l-wx------ 1 0 0 64  516 11:13 28 -> 'pipe:[112797695]'
lr-x------ 1 0 0 64  516 11:13 27 -> 'pipe:[112797695]'
lrwx------ 1 0 0 64  516 11:13 26 -> 'socket:[112797694]'
lrwx------ 1 0 0 64  516 11:13 25 -> 'socket:[112797692]'
l-wx------ 1 0 0 64  516 11:13 24 -> 'pipe:[112797576]'
lr-x------ 1 0 0 64  516 11:13 23 -> 'pipe:[112797576]'
l-wx------ 1 0 0 64  516 11:13 22 -> 'pipe:[112797575]'
lr-x------ 1 0 0 64  516 11:13 21 -> 'pipe:[112797575]'
lrwx------ 1 0 0 64  516 11:13 20 -> 'socket:[112797574]'
l-wx------ 1 0 0 64  516 11:13 2 -> /dev/null
lrwx------ 1 0 0 64  516 11:13 19 -> 'socket:[112797572]'
l-wx------ 1 0 0 64  516 11:13 18 -> 'pipe:[112797571]'
lr-x------ 1 0 0 64  516 11:13 17 -> 'pipe:[112797571]'
l-wx------ 1 0 0 64  516 11:13 16 -> 'pipe:[112797570]'
lr-x------ 1 0 0 64  516 11:13 15 -> 'pipe:[112797570]'
lrwx------ 1 0 0 64  516 11:13 14 -> 'socket:[112797569]'
lrwx------ 1 0 0 64  516 11:13 13 -> 'socket:[112797567]'
l-wx------ 1 0 0 64  516 11:13 12 -> 'pipe:[112797509]'
lr-x------ 1 0 0 64  516 11:13 11 -> 'pipe:[112797509]'
l-wx------ 1 0 0 64  516 11:13 10 -> 'pipe:[112797508]'
l-wx------ 1 0 0 64  516 11:13 1 -> /dev/null
lr-x------ 1 0 0 64  516 11:13 0 -> /dev/null
root@bcs-KVM:~#

정리

  • 시스템으로부터 할당 받은 파일을 대표하는 0이아닌 정수값
  • 프로세스에서 열린 파일의 목록을 관리하는 테이블의 인덱스
  • 흔히 유닉스 시스템에서 모든것을 파일이라고함
  • 일반적인 정규파일(Reglular File) 에서부터 디렉토리(Directory), 소켓(Socket), 파이프(PIPE), 블록 디바이스, 캐릭터 디바이스 등등 모든 객체들은 파일로써 관리된다.
  • 유닉스 시스템에서 프로세스가 이 파일들을 접근할때 파일 디스크립터(File Descriptor)라는 개념을 이용한다.
  • 파일 디스크립터는 '0'이아닌 정수, 'Non-negative Integer' 값이다. 즉, 음수가 아닌 0과 양수인 정수 값을 갖는다. (unsigned int 값이다.)
  • 프로세스가 실행 중에 파일을 open 하면 커널은 해당프로세스의 파일 디스크립터 숫자 중에 사용하지 않는 가장 작은 값을 할당해준다.
  • 그 다음 프로세스가 열려있는 파일에 시스템 콜을 이용해서 접근할 때, FD(해당 프로세스의 open file을 관리하는 구조체 배열의 index)값을 이용해 지징 할 수 있다.

참고

  • 프로그램이 프로세스로 메모리에서 실행을 시작 할 떄, 기본적으로 할당되는 파일 디스크립터들이 있다.
  • 바로 표준 입력, 표준 출력, 표준 에러이다. 이들에게 각각 0,1,2라는 정수가 할당되며, 이 매크로는 <unitsh.h> 헤더에서 찾아 볼 수있다.
  • 0이 아닌 정수로 표현되는 파일 디스크립터는 0~ OPEN_MAX까지 값을 가진다.

정리하자면 파일 디스크립터는 파이프, FIFO, 소켓, 터미널, 디바이스, 일반파일 등 종류에 상관없이 모든 열려있는 파일을 참조할때 쓴다.

파일 디스크립터목적POSIX 이름stdio 스트림
0표준입력STDIN_FILENOstdin
1표준출력STDOUT_FILENOstdout
2표준에러STDERR_FILENOstderr
  • 표에 있는 3가지 디스크립터는 프로그램이 시작할때 셸의 디스크립터의 복사본을 상속 받고, 셸은 보통 3가지 파일 디스크립터가 언제나 열린채로 동작 한다.
    -프로그램에서 파일 디스크립터를 참조할때는 번호(0,1,2)를 쓸 수도 있지만 가능하면 "UNISTD.H"에 정의된 POSIX 이름을 쓰는편이 좋다.

파일 디스크립터와 열려 있는 파일의 관계

  • 각 프로세스별로 커널은 open file descriptor table 을 갖고 있다. 테이블의 각 엔트리는 하나의 파일 디스크립터에 대한 동작 제어 플래그, 열린 파일을 가리키는 참조를 담고 있다
  • open file description은 현재 파일의 offset, flag, 접근 모드, i/o 관련 설정, 파일의 i-node 객체를 가리키는 레퍼런스를 갖고 있다.
  • i-node는 파일 종류 (일반파일, 소켓, fifo)와 권한, lock 목록 포인터, 여러 파일 오퍼레이션과 다양한 파일 속성(크기, 타임스탬프등)을 갖고 있다.
  • 만약 같은 open file description을 가리키는 2개의 fd는 offset값을 공유 한다.
profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글