파일 디스크립터를 닫으면 어떻게됩니까?


16

파일 설명 자로 전체 그림을 얻으려고합니다. 처음에 이러한 파일 설명자가있는 process1이 있다고 가정 해보십시오.

 _process1_
|          |
| 0 stdin  |
| 1 stdout |
| 2 stderr |
|__________|

그런 다음 파일 설명자 1을 닫습니다.

close(1);

파일 디스크립터 1 은 커널의 Open Files Table 에서 stdout FILE 구조 로 변환 (포인트)합니다 .

위의 코드를 사용하면 파일 디스크립터 1이 프로세스 테이블에서 삭제되어 다음과 같이됩니다.

 _process1_
|          |
| 0 stdin  |
| 2 stderr |
|__________|

그러나 커널은 어떻게됩니까? 않습니다 stdoutFILE 구조는 할당 해제? stdout이 특수 파일 (모니터)이고 다른 프로세스에서 사용 중이라면 어떻게 가능합니까? 일반 파일 인 파일 구조 (예 : .txt)는 어떻습니까? 이러한 파일을 다른 프로세스에서 사용중인 경우 어떻게합니까?

답변:


13

파일 디스크립터 1은 커널의 열린 파일 테이블에서 stdout FILE 구조로 변환됩니다.

이것은 오해입니다. 커널의 파일 테이블은 사용자 공간 파일 구조와 관련이 없습니다.

어쨌든 커널은 두 가지 수준의 간접 지향을 가지고 있습니다. 파일 자체를 나타내는 내부 구조가 있으며 참조 횟수가 계산됩니다. 참조 카운트되는 "열린 파일 설명"이 있습니다. 그리고 참조 카운트되지 않은 파일 핸들이 있습니다. 파일 구조는 inode 자체를 가리키는 방법입니다. 열린 파일 설명에는 열린 모드 및 파일 포인터와 같은 내용이 포함됩니다.

close를 호출하면 항상 파일 핸들을 닫습니다. 파일 핸들이 닫히면 열린 파일 설명의 참조 수가 감소합니다. 0이되면 열린 파일 설명도 해제되고 파일 자체의 참조 횟수가 감소합니다. 그것이 0이 될 때만 커널의 파일 구조가 해제됩니다.

공유 리소스가 참조 카운트되기 때문에 한 프로세스가 다른 프로세스가 사용중인 리소스를 해제 할 가능성이 없습니다.


귀하의 답변에서 용어를 이해하는 데 약간의 어려움이 있습니다. 파일 포인터가 "파일 오프셋"을 의미한다고 생각합니다. 그게 무슨 뜻입니까? 또한 파일 핸들의 의미는 무엇 입니까?
Geek

"파일 오프셋"에 의해 올바른 것은 후속 읽기 또는 쓰기가 발생할 오프셋을 의미합니다. "파일 핸들"은 프로세스와 열린 파일 설명 사이의 링크 open입니다. 성공하면 다시 얻을 수 있습니다.
David Schwartz

6

이 경우 많은 일이 발생하지 않습니다. stdin, stdout 및 stderr은 모두 동일한 파일 설명 자의 복제 인 경향이 있습니다. 파일 디스크립터의 참조 카운터는 1 씩 감소합니다. 동일한 파일 디스크립터는 일반적으로 프로그램이 실행 된 쉘에 의해 유지되므로 파일 디스크립터를 유지해야합니다.

커널은 열려있는 모든 파일 (아이 노드)에 대한 참조 횟수를 유지합니다. 참조 카운트가 0보다 크면 파일이 유지됩니다. 열린 파일 핸들에 대해 별도의 카운터가 유지 될 것으로 기대합니다. 이것이 0에 도달하면 커널은 파일 핸들이 사용하는 메모리를 해제 할 수 있습니다.

파일 (디렉토리 항목 및 파일 핸들)에 대한 모든 참조가 제거되면 파일 시스템 코드는 재사용을 위해 inode를 표시합니다. 파일이 할당 한 모든 블록을 사용할 수 있습니다. 많은 파일 시스템은 inode의 블록 포인터가 해제 될 때 블록 포인터를 지 웁니다. 이로 인해 삭제 된 파일을 복구하기가 어렵습니다. 디스크 업데이트는 나중에 버퍼링되고 완료 될 수 있습니다.


1
두 가지 질문이 있습니다. (1) 파일 디스크립터가 실제로 계산됩니까? 당신은을 Control-D를 할 때 cat > some.file, 고양이는 표준 입력에 EOF를 얻을 수 있지만, 쉘은하지 않습니다. (2) 왜 참조 카운트입니까? 왜 가비지 수집 형식이 아닌가? 사용자 공간에서 GC가 훨씬 좋지 않습니까?
Bruce Ediger

BillThor의 답변 확대 : 일반적인 경우 stdin, stdout 및 stderr은 TTY 장치에 대한 열린 파일 핸들입니다. 따라서 파일 핸들을 닫으면 해당 TTY 장치가 여전히 남아 있으며 나중에 다시 열 수도 있습니다.
Patrick

1
@BruceEdiger : (1) 셸이 cat > some.file실제로 수행하는 작업을 포크 할 때 'some.file'을 열고 파일 설명자 1에 할당하면됩니다 exec("cat"). 프로세스가 exec () 될 때 열린 파일 디스크립터를 상속합니다.
Patrick

@BruceEdiger (2) 참조 카운팅은 동일한 유형의 다른 데이터 구조에 대한 포인터를 포함하지 않는 데이터 구조에 사용될 때 완벽하게 훌륭한 가비지 수집 형식입니다. 또한 이것은 커널 공간에서 일어나고 있습니다 (매우 중요하지는 않습니다).
Gilles 'SO- 악한 중지
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.