나는 fork()에 대한 매뉴얼 페이지를 읽었으며 "호출 프로세스에서 열려 있는 모든 파일 설명자가 복사되었습니다."와 같은 내용을 말합니다.
호출 프로세스가 해당 시점에 실행하고 있는 실행 가능한 바이너리의 파일 설명자가 해당 명령문에 포함되어 있는지 여부가 100% 명확하지 않습니다. 매뉴얼 페이지에 "모든 파일 설명자"라고 나와 있지만 open()
이를 사용하여 두 프로세스를 동기화하는 것보다 분기된 프로세스에 대해 동일한 실행 가능 바이너리를 사용하는 것이 더 쉬워 보이기 때문에 이것을 묻는 것입니다. 그렇다면 실제로도 복사된다면 왜 그럴까요?
답변1
실행 중인 바이너리에는 파일 설명자가 없고 메모리 맵만 있습니다.
ls -l /proc/self/fd
(예를 들어 및 Linux의 경우를 참조하십시오 cat /proc/self/maps
.)
물론 메모리 맵은 동일한 파일을 가리키지만 공유 라이브러리에서도 마찬가지입니다. 기본 프로그램 파일의 경우 실행 중인 프로세스에서 사용 중인 동안에는 Linux에서 쓰기가 허용되지 않습니다. (지난번에 확인했지만 공유 라이브러리에서는 작동하지 않습니다.)
답변2
실제로 무엇을 하려는지는 확실하지 않지만 Linux(및 일부 다른 시스템)에서는 open("/proc/self/exe", ...)
파일이 삭제되었거나 파일 시스템에 전혀 존재하지 않는 경우에도 작동합니다.
/dev/tty
(항상 호출 프로세스의 컨트롤 tty가 열리는 경우) 와 마찬가지로 /proc/self/exe
호출 프로세스에서 현재 실행 중인 파일이 항상 열립니다. 둘 다 프로세스가 참조한 열린 파일의 설명을 숨기는 "문" 역할을 하여 일반 파일처럼 액세스할 수 있도록 합니다.
이것은 프로세스가 가지고 있는 유일한 "숨겨진"/잠재적 파일 설명자가 아닙니다. 특히, 다음을 사용하여 파일의 메모리 맵을 생성할 수 있습니다. mmap(..., fd, ...)
닫아도 fd
맵은 삭제되지 않으며 프로세스는 파일 설명자로 파일에 대한 참조를 계속 유지합니다(Linux에서는 파일 설명자를 열어 다시 전송할 수 있습니다 /proc/self/map_files/<range>
).
다른 예로는 루트 디렉터리와 현재 작업 디렉터리( /proc/self/{cwd,root}
)가 있습니다. 그러나 열려 있는 fds를 통해 참조되는 디렉터리라도 다른 디렉터리와 마찬가지로 해당 의미는 일반 파일의 의미와 다릅니다. 특히 디렉터리에서 생성 파일을 삭제할 수 없습니다. 디렉터리에 있는 경우 아직 열려 있는 파일 설명자를 통해 삭제된 파일에 데이터를 계속 쓸 수 있습니다.