커널이 알지 못하는 사이에 프로세스가 새로운 프로그램을 실행할 수 있습니까? 일반적으로 프로그램이 실행 중일 때 커널은 시스템 호출(예: exec() 또는 fork())을 수신한 후 자체 프로세스를 제공합니다. 이 경우 모든 것이 커널을 통과하고 결국 ELF 핸들러와 같은 것을 사용하여 프로그램이 시작됩니다. 물론 실제로는 새로운 프로그램을 실행할 때 별도의 프로세스가 필요하지만, 그것이 필요하지 않다면 어떻게 될까요? 프로그램/프로세스 xhathat가 실행 가능한 바이너리를 파일 시스템(예, 시스템 호출을 통해)에서 자체 가상 메모리 영역으로 전송하고 해당 프로세스 내에서 실행을 시작할 수 있습니까? 이 경우 커널은 프로그램/프로세스 xhathat이 무엇인가를 하고 있다는 것만 알지만 프로그램 xhathat이 실행된다는 사실은 개별적으로 알 수 없습니다.
"커널은 모른다"는 것은...그게 무슨 뜻인가요?
내가 의미하는 바는 커널이 실제로 "프로그램을 시작/실행"하지 않는다는 것입니다(일반적으로 커널은 바이너리이든 shebang을 포함하는 해석된 스크립트이든 관계없이 항상 이 작업을 수행합니다). 간접적으로만 가능합니다. 예, 대용량 저장소에서 이 xhathat 프로세스의 메모리 영역으로 새 프로그램을 로드하지만 시작/실행하지 않으며 시작/실행도 인식하지 못합니다. exec() 및 fork()와 같은 다양한 시작/실행 커널 시스템 호출을 실행하지 않습니다. 예를 들어, 커널이 의식적으로 프로그램을 시작하지 않으면 해당 프로그램은 프로세스에도 나타나지 않습니다(왜냐하면 xhathat 프로세스 내의 "프로세스/실행"일 뿐이기 때문입니다). 따라잡을 수 있나요? 내가 아는 한, 바이너리 컴파일 프로그램(물론 해석된 프로그램)도 가능합니다. 나는 bash나 systemd 또는 프로그램/프로세스를 "시작/실행"하는 모든 것이 일반적으로 커널이 실제로 시작/실행(또는 이전에 언급한 것처럼 shebang 스크립트)을 수행한다는 것을 깨달았을 때만 이것을 생각했습니다. 그런데 이 사실을 알고 나니 꼭 이래야 하는 걸까?라는 생각이 들었습니다. 나는 당신의 대답을 받아들입니다. 반드시 이렇게 할 필요는 없습니다. 물론 일반적으로 이렇게 하는 것이 더 낫습니다(커널은 모든 프로그램/프로세스를 시작합니다). 그리고 그것이 완료되었습니다.
그런데, 제가 설명한 작업을 수행하려면 (간단히 말해서) 어떤 코어가 필요합니까? 머릿속에 떠오르는 유일한 것은 이 새 프로그램을 대용량 저장소에서 다운로드하는 것인데, 프로그램이 이미 중앙 저장소에 있고 대용량 저장소에서 별도로 다운로드할 필요가 없다면 어떻게 될까요? 커널과의 상호 작용 없이 프로세스가 새 프로그램/"프로세스" 실행을 직접 시작할 수 있습니까?
답변1
예, 가능합니다. 이미 실행 중인 프로세스는 새 프로그램을 프로세스의 가상 주소 공간의 적절한 위치에 로드(또는 매핑)하고, 필요한 경우 동적 로더를 로드하고, 스택에 필요한 데이터 구조를 설정한 다음 새 프로그램의 위치로 점프해야 합니다. 메모리의 진입점입니다. (이러한 작업 중 다수는 커널과 관련되어 있지만 새 프로그램을 로드하는 것과는 아무 관련이 없습니다.)
fork
프로세스는 커널의 도움 없이는 완전히 새로운 주소 공간을 생성할 수 없지만 런처는 새 프로그램이 실행된 후 제어권을 다시 얻을 것으로 기대해서는 안 되므로 일반적으로 큰 문제는 아니며 두 프로그램이 주소 공간을 공유하는 것은 중요하지 않습니다. 주소 공간.
바라보다그루그의Userland Exec의 설계 및 구현더 자세한 설명을 원하시면.
답변2
예, 아니오...
즉, 간단히 말해서 많은 프로그래밍 언어가 해석됩니다. 따라서 첫 번째 프로그램이 Python 인터프리터에서 실행되는 Python 프로그램인 경우 다른 파일을 가져와서 실행하기만 하면 됩니다.
인터프리터 대신 바이너리 프로그램을 사용하여 동일한 작업을 수행하는 것이 약간 더 어렵습니다.
"커널은 모른다"는 것은...그게 무슨 뜻인가요? 두 번째 프로그램은 어디에서 왔나요? 디스크에서 로드하셨나요? (커널이 이 작업을 수행합니다...) 네트워크에서 로드하고 있습니까? (커널도 이 작업을 수행합니다.) 실행 가능한 페이지를 교체하려는 경우 대부분의 경우 최신 커널은 실행 가능한 코드가 포함된 페이지나 실행될 코드가 포함된 쓰기 가능한 페이지 작성을 허용하지 않으므로 기본 머신을 업데이트해야 합니다. 새로운 내용을 해석하는 것보다 코드 페이지에서 커널은 이러한 페이지를 로드하고 실행 가능하게 만드는 데 관여해야 합니다.
프로세스는 커널의 직접적인 개입 없이는 다른 프로세스를 시작할 수 없습니다. 커널을 많이 사용하지 않고도 자체적으로 교체하거나 더 많은 실행 코드를 추가할 수 있지만 해당 페이지를 가져오기 위해 일종의 I/O를 수행할 필요는 없습니다.
커널은 다음과 같은 이유로 실행 중인 프로세스를 "알고 있습니다".
- 페이지 테이블 권한의 일부로 프로세스에서 실행할 수 있는 메모리의 페이지를 알고 있습니다. 이는 쉽게 우회할 수 없습니다.
- 일반적으로 이러한 실행 가능 페이지는 메모리에 매핑되고 요청 시 페이징되기 때문에 어떤 파일에서 나오는지 알고 있습니다. 즉, 커널은 요청 시 디스크에 있는 파일의 페이지를 메모리에 로드합니다. 이는 페이지가 이미 메모리에 캐시되어 있어도 페이지 캐싱 시스템의 일부로 계속 발생합니다.
- 커널은 초기 실행 파일을 시작하는 데 사용된 이름을 알고 있습니다.
- 커널은 프로세스가 시작될 때 명령줄과 환경을 알고 있습니다. 프로세스는 대부분의 시스템에서 이를 편집할 수 있지만
- 커널은 어떤 파일이 열려 있고 빨간색인지 알고 있습니다.
위의 대부분은 ps
모든 UNIX 시스템에서 이 명령을 사용하여 표시할 수 있습니다. 위의 모든 내용은 /proc/
Linux 시스템에서 사용할 수 있습니다(페이지 테이블 정보 제외).
그렇다면 exec()를 사용하지 않고 수행할 수 있습니까? 틀림없이! 어떤 방식으로든 커널을 개입시키지 않고 수행할 수 있습니까? 설마.