실제 주소를 알아내려고 합니다.페이지 테이블그러나 항상 실패했습니다.
내가 시도할 마지막 옵션은 계층적 페이지 테이블을 생성하거나 확장할 때 커널 코드를 수정하고 단순히 물리적 주소를 인쇄하는 것입니다.
그런데 페이지 테이블의 물리적 주소를 확인하는 다른 방법이 있을까요? 가상과 물리적 매핑을 찾기 위해 단순히 /proc/PID/pagemap을 읽는 것과 유사합니다.
답변1
여러 가지 오해.
- 최신 프로세서, 특히 aarch64, x86_64에는 페이지 테이블이 존재하지 않습니다. 메모리 공간에 임의로 분산할 수 있는 다단계 구조입니다. 찾을 수 있는 주소가 없습니다! 참조하는 아키텍처와 레벨을 지정해야 합니다.
- 반드시 모든 아키텍처가 실제로 물리적 주소 공간에 페이지 테이블 버전을 가지고 있는 것은 아닙니다. 특히 임베디드 프로세서 유형에는 이를 위한 내장 메모리가 있지만 RAM에는 전혀 없습니다. 다시 말하지만, 참조하는 아키텍처에 대해 구체적으로 설명해야 합니다.
- 모든 운영 체제가 동일한 것처럼 묻고 있습니다. 그러나 Linux가 페이지 테이블을 구축하고 mmu와 상호 작용하는 방식은 다른 Unixoid 운영 체제와 반드시 동일하지는 않습니다. 무슨 뜻인지 구체적으로 설명해야 합니다!
내가 시도할 마지막 옵션은 계층적 페이지 테이블을 생성하거나 확장할 때 커널 코드를 수정하고 단순히 물리적 주소를 인쇄하는 것입니다.
웃긴 건 그게 네 거라는 거야마지막옵션! 사용자 공간, 즉 자체 가상 메모리 공간에 대한 분할되고 보호된 액세스가 있는 프로세스는 일반적으로 Danny 물리적 주소를 볼 수 없습니다. 사실 이것은 제가 들어본 모든 운영 체제 드라이버 프레임워크에 대해 상당히 정해진 규칙입니다. 가상 메모리 공간의 프로세스에 물리적 메모리 주소가 노출되면 해당 항목이 손상된 것이므로 복구해야 합니다. 나쁜 규칙은 아닙니다. 사용자 공간이 조작된 물리적 주소를 커널에 반환하도록 허용하여 프로세스가 액세스해서는 안 되는 메모리에 액세스하는 위험한 실수를 방지합니다.
페이지 테이블을 확장할 때 인쇄 이외의 다른 작업을 수행하는 것이 좋습니다. 이는 나쁜 생각입니다. 왜냐하면 그것이 의미하는 바가 무엇이든 버퍼가 커져서 더 많은 메모리를 할당하여 잠재적으로 무한 루프가 발생할 수 있기 때문입니다. 다양한 BSD 커널 및 Linux에서 프로브를 사용하여 이러한 위치에 연결할 수 있습니다.
요약하면, 클래식 32비트 x86에서 링 0에 있을 때 레지스터는 cr3
페이지 테이블의 주소를 보유하는 현재 활성 페이지 디렉토리의 주소를 보유합니다. 이러한 페이지 테이블에 바인딩된 프로세스는 이 레지스터에 액세스할 수 없어야 합니다.
이제 메모리에 실제로 적용되는 뷰는 cr4, 즉 프로세스 컨텍스트 식별자가 설정되어 있는지 여부에 따라 달라집니다.
따라서 페이지 테이블 주소에 액세스하려면 "커널 모드"(원하는 경우)에서 실행해야 하지만 관심 있는 프로세스의 페이지 디렉터리 기본 주소를 CR3에 로드해야 합니다. 디버거를 통해 커널 메모리에서 직접 데이터를 가져올 수도 있습니다. 마지막으로 다른 작업으로 전환하려면 현재 작업에 필요할 때 사용할 수 있도록 일부(OS별) 구조에 기본 주소를 저장해야 합니다.
가상화를 사용하면 "물리적 주소"는 실제로 중첩된 페이지 테이블 구조에서 한 수준 위일 수 있습니다. 반가상화된 운영 체제의 커널은 "실제" 물리적 주소를 결코 볼 수 없지만 iommu/smmu 개념을 고려할 때 여기서 "실제"라는 단어가 얼마나 의미가 있는지조차 확신할 수 없습니다.