Unix 계열 시스템이 동적 라이브러리 대신 함수를 호출할 때 왜 새로운 프로세스를 실행합니까? 새로운 프로세스를 생성하는 것은 동적 라이브러리를 호출하는 것에 비해 성능 측면에서 비용이 많이 듭니다.
답변1
유닉스 계열 시스템은 "새 프로세스를 실행하여 함수를 호출"하지 않습니다. 그들은 (현재) 상대적으로 현대적인 거의 모든 운영 체제와 마찬가지로 공유 라이브러리를 가지고 있습니다.
반면에 셸은 특정 작업을 수행하기 위해 다른 프로세스를 실행합니다. 그러나 전부는 아닙니다. 여기에는 쉘에서 직접(또는 공유 라이브러리를 통해) 가장 일반적이고 간단한 작업을 구현하는 내장 함수가 있습니다( echo
예: 많은 쉘에서 내장 함수로 구현됨).
(그런데 Windows cmd
쉘은 이 점에서 Unix 쉘과 다르지 않습니다.)
프로세스를 생성하는 것은 확실히 최신 Unix 계열 시스템에서 프로세스 내 함수 호출을 수행하는 것보다 비용이 더 많이 들지만 그다지 큰 비용은 아닙니다. 커널은 다음 기술을 사용하여 빠른 포크에 최적화되어 있습니다.쓰기 중 복사프로세스의 "복제" 속도를 높이고 동적 라이브러리의 텍스트(코드) 페이지를 공유하기 위한 주소 공간 관리에 사용됩니다.
쉘 스크립트에서 호출할 수 있는 컴퓨터의 모든 실행 파일이 공유 라이브러리로 구현된 경우:
- 쉘을 시작하려면 다음이 필요합니다.많은이 모든 것을 미리 로드하는 데 필요한 시간(및 메모리)(캐싱을 사용하더라도 동적 링커에는 수행할 중요한 작업이 있으며 라이브러리에는 텍스트 부분뿐만 아니라 데이터 부분도 있습니다. 수천은 아니더라도 수백에 해당합니다. 라이브러리는 여기)
- 요청 시 필요한 모든 라이브러리를 로드해야 합니다. 프로세스를 시작하는 것보다 조금 더 빠를 수도 있지만 여기서의 이점은 매우 약합니다. 그리고 공유 라이브러리의 데이터 부분은 관리하기가 매우 어려워집니다(셸의 전역 상태는 이제 주소 공간에 로드된 관련 없는 코드와 데이터의 상태에 따라 달라집니다).
따라서 일반적인 사용에서는 아마도 많은 이점을 얻지 못할 것이며 안정성/복잡성이 더 중요해집니다.
또 다른 점은 별도의 프로세스 모델이 각 작업을 매우 효과적으로 분리한다는 것입니다(가상 메모리 관리 및 보호 가정). "모든 것이 라이브러리입니다" 모델에서는 유틸리티 라이브러리의 버그가 전체 셸을 오염(즉, 손상)시킬 수 있습니다. 일부 임의 유틸리티의 버그로 인해 쉘 프로세스가 완전히 중단될 수 있습니다.
이는 쉘이 실행하는 프로그램에서 그러한 오류를 피할 수 있는 다중 프로세스 모델의 경우에는 해당되지 않습니다.
한 가지 더: 낮은 결합도. /usr/bin
지금 디렉토리의 내용을 보면 다음과 같습니다 .
- ELF 64비트 실행 파일,
- ELF 32비트 실행 파일,
- 펄 스크립트,
- 쉘 스크립트(일부는 Java 프로그램을 실행함),
- 루비 스크립트와
- 파이썬 스크립트
...아마도 저는 가장 멋진 시스템을 갖고 있지 않을 것입니다. 동일한 프로세스에서 처음 두 유형을 혼합할 수는 없습니다. 다른 사람을 위해 통역사를 두는 것은 전혀 실용적이지 않습니다.
"네이티브 바이너리" 파일 형식만 보는 경우에도 "유틸리티" 간의 인터페이스는 간단한 스트림과 종료 코드이므로 작업이 더 간단해집니다.
유틸리티에 대한 유일한 요구 사항은 운영 체제의 ABI 및 시스템 호출을 구현하는 것입니다. 서로 다른 유틸리티 간에는 종속성이 (거의) 없습니다. In-Process 인터페이스의 경우 "모든 것은 이러한 플래그/설정을 사용하여 컴파일러 Y의 버전 X로 컴파일되어야 합니다."와 같은 규정을 부과하지 않는 한 이는 매우 어렵거나 불가능합니다.
프로세스 내 호출이 성능에 큰 영향을 미치는 몇 가지 작업이 있으며 이러한 작업은 셸에서 기본 제공으로 이미 수행되는 경우가 많습니다. 나머지 경우에는 별도의 프로세스 모델이 매우 잘 작동하며 유연성이 큰 장점입니다.