리눅스 커널의 내부 구조, 프로세스 관리, 프로세스의 컨텍스트 전환 등을 이해하려고 노력합니다. 내가 이해한 튜토리얼(이 커뮤니티, IBM 등)에 따르면 전원 버튼을 누르면 부트로더가 커널을 로드합니다. 그런 다음 스케줄러를 시작하고 다른 모든 프로세스의 시작을 담당하는 최종 init 프로세스를 생성합니다.
따라서 얼마 후 컨텍스트 전환이 발생합니다. 이 컨텍스트 전환 동안 커널은 새 프로세스의 페이지 테이블을 보고 (필요한 경우) MMU의 TLB에 로드합니다. 커널이 전체 페이지 테이블(32비트 시스템에서 4GB의 가상 메모리)을 MMU에 로드합니까? 내가 이해한 바에 따르면 상위 1GB의 메모리가 커널 메모리이므로 모든 프로세스에서 스왑 아웃되지 않고 거기에 있을 것이기 때문에 이 테이블 스왑은 어떻게 작동합니까? 모든 프로세스의 페이지 테이블에는 처음 1GB 메모리에 대한 직접 매핑이 포함되어 있으므로 처음 1GB의 가상 메모리가 처음 1GB의 실제 메모리에 직접 매핑됩니까?
나 같은 멍청한 놈을 위해 이것을 설명하는 문서를 찾을 수 없기 때문에 이 컨텍스트 전환이 어떻게 작동하는지에 대한 일종의 문서가 있습니까?
답변1
각 프로세스에는 32비트 x86 시스템에서 하위 3GB에 이르는 자체 페이지 세트가 있습니다. 32비트 시스템의 처음 1GB는 모든 프로세스에 공통되며 사용자 공간에서 액세스할 수 없습니다. 상위 1GB는 커널용으로 예약되어 있으며 처음에는 전체 물리적 RAM 오프셋 3GB의 맵을 포함합니다. 즉, 물리적 메모리 주소 0은 가상 주소 0xc0000000에서 볼 수 있고, 물리적 메모리 주소 1은 주소 0xc0000001에서 볼 수 있는 식입니다. 메모리 크기가 1GB 제한을 초과하면 "highmem" 창을 통해 초과된 물리적 메모리에 액세스하기 시작합니다.
x86-64에서 주소 공간의 위쪽 절반은 커널용으로 예약되고 아래쪽 절반은 사용자 공간용으로 예약됩니다. 현재 하드웨어에서는 전체 64비트 주소 공간의 사용을 허용하지 않습니다. 일반적으로 48개의 주소 비트만 사용할 수 있으며 상위 16비트는 모두 0이거나 모두 1이어야 합니다. (사용 가능한 정확한 비트 수는 CPU 모델에 따라 다릅니다.)
컨텍스트 전환 시 맵의 사용자 공간 부분은 새 프로세스의 맵으로 대체되지만 커널 부분은 변경되지 않습니다. 4GB 메모리 공간 전체가 매핑되지 않고 실제로 사용되는 부분만 매핑됩니다. 이를 통해 더 작은 페이지 테이블 트리를 사용할 수 있습니다. 초기 매핑은 실행할 프로그램이 포함된 ELF 파일에 의해 결정됩니다. 새 메모리가 동적으로 할당되거나 매핑이 사용 mmap
되거나 스택이 자동으로 확장되면 필요에 따라 페이지 테이블이 수정됩니다.
스케줄러는 별도의 프로세스가 아니기 때문에 "시작"되지 않습니다. 커널은 실행 중인 프로세스가 입력이나 다른 이벤트를 기다려야 할 때 또는 현재 프로세스가 해당 시간 조각을 모두 소진했을 때 프로세스의 일정을 다시 잡습니다. 각 프로세스는 이벤트 대기, 실행 준비, 실행 등 여러 상태 중 하나에 있습니다. 커널이 일정을 변경하면 실행할 준비가 된 프로세스 목록을 확인하고 다음에 실행할 프로세스 하나(CPU당)를 선택합니다.
또한 TLB(변환 색인 버퍼)는 커널(x86 프로세서)에 의해 직접 로드되지 않습니다. 소프트웨어는 페이지 테이블만 수정하며, 하드웨어는 런타임 시 필요에 따라 TLB의 항목을 자동으로 채웁니다. TLB는 소프트웨어로 새로 고칠 수 있습니다. 이는 컨텍스트 전환에서 수행되어야 합니다.
Linux 커널 내부에 관해 몇 권의 책(예: "Linux 커널 이해")이 작성되었지만 대부분은 상당히 오래된 것입니다. 하지만 더 이상 좋은 참고자료는 아니지만, 그 중 상당수는 관련 정보를 제공하지만, 많은 것이 바뀌었다는 점을 기억해야 합니다.