0xc00000000
내 책 중 일부에서는 Linux 커널이 32비트 시스템 에 상주하며 성능상의 이유로 사용자 공간에 매핑된다는 점을 노트에 언급했습니다 .
이것이 정확합니까? 이를 어떻게 확인하나요?
또한 64비트 시스템에서 커널은 어디에 있습니까? 아직 거기에 있나요 0xc00000000
, 아니면 다른 곳에 있나요?
답변1
물리적 메모리
실제 메모리에서 커널은 일반적으로 위의 임의 오프셋에 상주합니다 0x1000000
. 이는 커널 구성 옵션과 CONFIG_PHYSICAL_START
커널 명령줄 옵션/에 따라 달라집니다.CONFIG_PHYSICAL_ALIGN
CONFIG_RANDOMIZE_BASE
kaslr
nokaslr
리눅스 내부자 책.
가상 메모리(32비트)
32비트 아키텍처에서 가상 주소 공간 분할은 커널 구성 옵션에 따라 다릅니다.CONFIG_PAGE_OFFSET
많은 아키텍처에서 이는 CONFIG_VMSPLIT_*
옵션에 의해 암시적으로 설정됩니다. 커널의 구성은 일반적으로 커널 이미지와 함께 구성되므로 /boot/config-<version>
커널 영역이 시작되는 가상 메모리에서 오프셋을 확인할 수 있습니다 grep PAGE_OFFSET "/boot/config-$(uname -r)"
. x86의 일반적인 구성은 CONFIG_VMSPLIT_3G
0xC0000000을 0xC0000000으로 설정하여 PAGE_OFFSET
커널용 주소 공간의 상위 1GiB를 예약하는 것입니다. 성능상의 이유로 이 매핑은 모든 사용자 공간 프로세스를 포함하여 모든 가상 주소 공간에서 동일하게 유지됩니다.
커널 코드가 시작되는 정확한 주소는 이 영역 어딘가에 있으며 부팅 시 무작위로 지정될 수 있습니다. 이는 물리적 주소 무작위화와 동일한 구성 및 커널 명령줄 설정에 따라 달라집니다.
가상 메모리(64비트)
64비트 아키텍처에서는 주소 공간이 훨씬 더 크기 때문에 상황이 다릅니다.
세부 사항은 아키텍처에 따라 다르지만 일반적으로 커널은 주소 공간 상단의 메모리 범위에 상주합니다.
x86-64
x86-64(일명 AMD64)에서 메모리 레이아웃은 다음과 같습니다.잘 기록 된. 하드웨어 지원 및 구성 옵션에 따라 두 가지 구성이 가능합니다 CONFIG_X86_5LEVEL
.
시작(4단계 페이징) | 치수(레벨 4 페이지) | 시작(5단계 페이징) | 차원(레벨 5 페이지) | 설명하다 |
---|---|---|---|---|
0xFFFF800000000000 |
8 티타늄 붕소 | 0xFF00000000000000 |
4PiB | 하이퍼바이저용으로 예약된 보호 구멍 |
0xFFFF880000000000 |
0.5TiB | 0xFF10000000000000 |
0.25PiB | PTI의 LDT 리매핑 |
0xFFFF888000000000 |
64 티타늄 붕소 | 0xFF11000000000000 |
32 스킨B | 모든 물리적 메모리의 직접 매핑 |
0xFFFFC90000000000 |
32TB | 0xFFA0000000000000 |
12.5PiB | vmalloc/ioremap 공간 |
0xFFFFEA0000000000 |
1TB | 0xFFD4000000000000 |
0.5PiB | 가상 메모리 매핑 |
0xFFFFEC0000000000 |
16TB | 0xFFDF000000000000 |
8PiB | 카산 섀도우 메모리 |
여기에서도 같은 레이아웃 | ||||
0xFFFFFE0000000000 |
0.5TB | cpu_entry_area 매핑 | ||
0xFFFFFF0000000000 |
0.5TB | %esp 수리 스택 | ||
0xFFFFFFEF00000000 |
64GB | EFI 영역 매핑 공간 | ||
0xFFFFFFFF80000000 |
512MB | 커널 텍스트 맵, 물리적 주소 0에 매핑됨 | ||
0xFFFFFFFFA0000000 |
1520MB | 모듈 매핑 공간 | ||
FIXADDR_START |
~0.5MB | 매핑 범위, 가변 크기 및 오프셋에 대한 커널 내부 수정 | ||
0xFFFFFFFFFF600000 |
4KB | 레거시 vsyscall ABI |
따라서 커널 영역은 0xFFFF800000000000
또는 에서 시작 0xFF00000000000000
하고 커널 코드는 에서 시작하는 영역에 (일반적으로 임의 오프셋에) 상주합니다 0xFFFFFFFF80000000
.
ARM64
64비트 ARM의 경우메모리 레이아웃은 x86-64의 레이아웃과 다소 유사합니다.. 정확한 분할은 커널 구성(4kB/64kB 페이지, 2/3/4 레벨 페이징)에 따라 다릅니다.
페이지 크기 | 페이징 수준 | 커널 영역 시작 주소 |
---|---|---|
4KB | 삼 | 0xFFFFFF8000000000 |
4KB | 4 | 0xFFFF000000000000 |
64KB | 2 | 0xFFFFFC0000000000 |
64KB | 삼 | 0xFFFF000000000000 |
답변2
이제는 aslr로 인해 임의의 위치에 있습니다(파일을 64비트 시스템에서 컴파일했다고 가정하면 2016년이므로 64비트 시스템을 실행해야 하기 때문에 그렇게 하지 않을 이유가 없습니다.... .시스템이 낮은 수준인 경우) 64비트 커널 + 메모리의 32비트 사용자 영역만 실행)