ZONE 타입

<kernel v5.0>

리눅스에서 물리 메모리 주소 영역을 ZONE 단위로 구분하여 관리한다. 각각의 ZONE은 다음과 같다.

  • ZONE_DMA
  • ZONE_DMA32
  • ZONE_NORMAL
  • ZONE_HIGHMEM
  • ZONE_MOVABLE
  • ZONE_DEVICE

 

ZONE_DMA & ZONE_DMA32

DMA(Direct Memory Access)를 사용하여 메모리에 직접 접근하는 디바이스들을 사용하는 시스템에서 DMA를 사용하는 디바이스가 해당 시스템이 사용하는 주소 버스를 모두 커버하는 경우에는 별도로 ZONE_DMA를 구성할 필요 없이 기본 적으로 만들어지는 ZONE_NORMAL을 사용하여 메모리를 할당받아 사용할 수 있다. 그러나 DMA를 사용하는 디바이스가 시스템이 지원하는 물리 메모리 주소보다 작은 경우에는 별도로 ZONE_DMA를 구성해서 DMA 디바이스용으로 메모리 할당을 제한된 주소 미만으로 만들어놔야 그 DMA 디바이스가 접근할 수 있게된다. x86 및 arm의 경우 다음과 같은 조건에 따라 CONFIG_ZONE_DMA 및 CONFIG_ZONE_DMA32 사용 유무를 결정해서 사용한다.

  • DMA를 사용하는 디바이스 장치의 주소 버스가 시스템의 최대 물리 메모리 접근 주소까지 접근될 수 있게 설계된 경우 CONFIG_DMA를 설정할 필요 없다. 그러나 DMA를 사용하는 디바이스 장치의 주소 버스가 시스템의 최대 물리 메모리 접근 주소보다 접근할 수 없는 경우 CONFIG_DMA를 설정해서 사용한다.
    • 32bit x86:
      • CONFIG_ZONE_DMA 사용
    • 64bit x86:
      • CONFIG_ZONE_DMA 및 CONFIG_ZONE_DMA32 사용
    • arm:
      • default 로 ZONE_DMA를 사용하지 않는다. 단 특정 시스템의 경우 ZONE_DMA를 사용하고 사이즈를 지정하여 운영한다.
    • arm64:
  • DMA 컨트롤러 및 채널 참고

 

DMA 사이즈 설정

  • 32bit x86
    • 16MB로 고정되어 자동 구성된다.
    • 24bit address bus를 사용한 AT(80286) 시스템에 채용된 ISA 버스에서 동작하는 디바이스를 호환(backward compatible)시키기 위해 사용된다
  • 64bit x86
    • 4GB로 고정되어 자동 구성된다.
    • 32bit address만을 사용하는 기존 버스들(32bit EISA, PCI,  24bit ISA, …)에서 동작하는 디바이스를 호환시키기 위해 사용된다.
  • 32bit ARM
    • CONFIG_DMA를 사용하는 경우 DMA size가 flexible하게 구성된다.
    • 임베디드 시스템 회로(Circuit) 구성이 DMA 디바이스 장치에서 제한된 address bus 핀(pin)만 사용하는 경우 그 지정할 수 있는 주소만큼 영역을 제한시킨다.
      • 예) arm32에서 DMA 디바이스 장치가 28 bit address bus를 지원하는 경우
        • DMA size는 256MB로 설정해야 한다.
  • 64bit ARM
    • 물리 메모리 시작 주소를 기준으로 최대 4GB 까지의 물리 메모리 주소로 자동 구성된다.

 

다음 그림은 DMA를 사용하는 디바이스 장치가 어느 때 CONFIG_DMA를 설정해야 하는지를 나타낸다.

zone-dma-1

  • DMA를 사용하는 디바이스 장치가 32비트 주소를 지원하므로 특별히 ZONE_DMA를 설정할 필요 없다.

 

zone-dma-2

  • DMA를 사용하는 디바이스 장치가 제한된 24비트 주소만을 지원하는데 32비트 주소로 할당된 메모리는 디바이스 장치에서 접근할 수 없다.

 

zone-dma-3

  • DMA를 사용하는 디바이스 장치가 제한된 24비트 주소만을 지원하므로 관련 메모리 할당을 ZONE_DMA 영역에서 할당을 받아 사용한다.
    • ZONE_DMA 사이즈를 64MB(2^26)로 설정하여 사용한다.

 

ZONE_NORMAL

  • 시스템에서 지원하는 물리 메모리가 아키텍처의 가상 주소에 1:1로 미리 매핑되어 사용할 수 있는 만큼의 영역이다. 따라서 커널 메모리 할당 시 ZONE_DMA 영역과 함께 가장 빠르게 접근할 수 있는 메모리 영역이다.
    • 32bit 시스템에서는 4G의 공간을 user space와 kernel space로 나누어 사용하므로 user space는 비워두고 kernel space의 일부 영역을 사용하여 물리 메모리를 배치하는데 이에 사용된 물리 메모리 영역이 ZONE_NORMAL이다.
      • 32bit arm
        • 커널 크기 구성에 따라 다르다.
          • CONFIG_VMSPLIT_3G
            • normal zone의 최대 영역 크기=760MB
            • user space가 3G, kernel space가 1G
            • 대부분의 PC 리눅스와 임베디드 커널에서 사용한다.
          • CONFIG_VMSPLIT_2G
            • normal zone의 최대 영역 크기=1GB + 760MB
            • user space가 2G, kernel space가 2G
            • 라즈베리파이2 및 일부 임베디드 시스템이 사용하는 설정이다.
          • CONFIG_VMSPLIT_1G
            • normal zone의 최대 영역 크기=2GB + 760MB
            • user space가 1G, kernel space가 3G
            • 극단적인 설정이라 거의 사용되지 않는다.
      • 32bit x86
        • normal zone의 최대 영역 크기=896MB
    • 물론 ZONE_DMA 및 ZONE_DMA32도 가상 주소에 1:1로 매핑되어 있다.
    • 32 비트 시스템에서 normal zone은 크기가 제한되어 있으므로 최대한 커널 할당에 사용되는 비싼 영역이다.
    • 64bit ARM인 ARMv8 아키텍처에서는 최대 커널 주소 공간이 256T이고 그 중 절반의 공간인 128T 공간을 물리 메모리 배치로 사용할 수 있다. 즉 거대한 normal zone이며, 이 공간이 매우 크기 때문에 별도의 highmem zone을 생성해야할 이유가 없다.
      • ARMv8.2 아키텍처부터는 최대 52bit 물리 주소를 지원하여 4 Peta 공간을 지원한다.

 

다음 그림은 32bit 시스템에서의 ZONE_NORMAL 영역이 제한되어 있음을 보여준다.

zone-2a

 

ZONE_HIGHMEM

ZONE_NORMAL이 처리하지 못하는 메모리 영역이 모두 ZONE_HIGHMEM으로 구성된다.

  • 32bit 시스템에서는 1:1 매핑이 일부만 가능하기 때문에 ZONE_NORMAL을 초과하는 메모리가 이 영역을 사용한다.
  • 64bit 시스템에서는 모든 물리 메모리가 1:1 매핑이 가능하므로 ZONE_HIGHMEM을 사용하지 않는다.
  • user 메모리의 할당 시 우선적으로 highmem 영역의 메모리를 먼저 소모시키고, 이를 다 소모한 경우에 한해 normal zone 영역을 사용한다.

 

ZONE_MOVABLE

이 영역은 아래와 같이 두 가지 목적으로 사용한다.

  • 단편화 방지
    • 마지막 zone에 대해서 각 노드의  일부 영역을 할당하여 버디 시스템으로 구현된 페이지 할당자가 메모리 파편화를 막기 위해 이 영역을 전용으로 사용한다.
    • 이 영역을 구성하지 않아도 버디 시스템은 migration 타입으로 분류하여 최대한 파편화를 막는데, 이 영역을 지정하는 경우 이 영역 전체가 movable 페이지 구성이 되므로 파편화를 막는데 더욱 큰 효율을 보일 수 있다.
    • 마지막(last) zone이란 것은 시스템에 설치된 zone 중 가장 상위에 존재하는 zone으로 시스템에 따라 가장 다른데 아래와 같이 높은 순부터 낮은 순으로 나열한다.
      • ZONE_HIGHMEM -> ZONE_NORMAL -> ZONE_DMA(또는 ZONE_DMA32)
      • ZONE_HIGHMEM이 없는 64비트 시스템에서는 ZONE_NORMAL이 될 수 있고 그것도 없는 경우 ZONE_DMA(또는 ZONE_DMA32)가 될 수 있다.
  • 핫플러그 메모리 지원
    • 버디 시스템의 메모리 파편화도 막으면서 동시에 최근에 구현된 “메모리 Hotplug”를 지원하기 위해 메모리 Hotplug를 원하는 노드 전체를 ZONE_MOVABLE로 구성하여 사용한다.

 

다음 그림은 NUMA 32bit ARM 시스템에서의 ZONE_MOVABLE 구성을 보여준다.

zone-3

 

다음 그림은 64bit ARM 시스템에서의 ZONE_MOVABLE 구성을 보여준다.

  • 커널 v4.16-rc1 부터 ZONE_DMA 대신 ZONE_DMA32를 사용한다.

zone-4

 

ZONE_DEVICE

  • 커널 v4.3에 새롭게 추가되었으며 대용량 persistent memory 디바이스 및 heterogeneous memory 디바이스 등에서 사용하기 위한 영역이다.
    • ZONE_DMA는 디바이스가 cpu의 주 메모리에 대한 접근을 하고자 하는 것과 비교를 해보면 ZONE_DEVICE는 다음을 추구한다.
      • cpu가 대용량의 디바이스 메모리에 접근하고자 한다.
        • persistent memrory 예) 주 메모리가 8G, 고속 디바이스 메모리가 512G
        • heterogeneous memory 예) 주 메모리가 2G, GPU 디바이스 메모리가 6G
      • 고속 처리를 위해 CPU 및 디바이스 측에서 캐시를 사용하고자 한다.
      • 동시성
        • 양쪽에서 h/w cache coherent가 동작되고자 한다.
        • cpu 측에서 atomic operation을 사용하고자 한다.
  • 필요조건
    • 메모리 핫플러그 및 핫리무브가 지원되어야 하며 64비트에서만 사용하는 SPARSEMEM_VMEMMAP 설정이 필요하다.
  • 서버급인 x86_64 및 PPC_64 아키텍처부터 구현되고 있다.
  • persistent memory 디바이스에 유저스페이스를 이용하는 DAX 매핑을 사용할 수도 있다.
  • heterogeneous memory 디바이스에서 접근하는 메모리를 CPU에서도 접근할 수 있다. (CONFIG_HMM)
    • 커널 v4.14에 추가되었다.
    • 전체 영역 또는 일부 영역을 지정한다.
    • ZONE_DEVICE를 통해 메모리 swap 장치로 사용할 수 있다.
    • private(CONFIG_DEVICE_PRIVATE)으로 설정된 HMM 메모리는 디바이스에서만 접근할 수 있고, CPU에서는 접근할 때에는 커널의 일반 메모리 관련 API를 사용하지 못하고,  HMM 전용 API를 통해서만 접근할 수 있다.
    • public(CONFIG_DEVICE_PUBLIC)으로 설정된 HMM 메모리는 디바이스와 CPU 양쪽에서 접근할 수 있다.
      • 커널에서 사용하는 모든 메모리 API들을 사용하여 접근할 수 있다.
      • 양방향 매핑에 대한 동기화 및 cache coherent 문제를 해결하도록 h/w가 지원해야 한다.
  • 고속 인터페이스
    • 가장 빠른 것은 디바이스 메모리가 SoC에 임베드되어 내부 고속 버스에 통합되는 경우이다.
      • 임베드된 GPU가 사용하는 GDDR 메모리
    • 외부 버스 중 가장 빠른 DRAM 메모리 버스를 사용할 수도 있다
      • 인텔의 옵테인 메모리(고가이며 CPU가 지원해야한다.)
    • PCIe를 사용하는 가장 대중화된 외부(시스템이 아닌 칩 외부) 고속 인터페이스이다.
      • 고속 SSD 및 인텔의 옵테인 메모리(CPU가 지원하지 못할 때 사용할 수 있는 저가용)
        • 참고로 기존 SSD가 연결되는 인터페이스는 SATA부터 출발했지만 현재는 PCIe를 사용하는 AHCI와 NVMe(AHCI보다 더 빠른 프로토콜)가 있다.
      • pc 장착용 GPU들도 PCIe를 사용한다.
      • 메모리 접근 속도에 비해 수십배 느린 PCIe 버스를 사용해야 하므로 CPU에서 접근할 때에는 느린 제약이 있다.
      • 디바이스 메모리에 대한 atomic operation 및 cache coherent 등이 그동안 지원되지 않았으며 최근에는 가능해졌다.
  • 참고:

 

참고

 

 

21 thoughts to “ZONE 타입”

  1. 리눅스 커널에 대해 공부하던중에 ZONE타입에 대해서 이해 못하고있었는데 이글보고 이해했네요. 좋은글 감사합니다.

    1. 독자의 이해도를 고려하지 않고 글을 막(?) 쓰다보니 대부분의 분들이 제 글이 어렵다고 하십니다. ^^;
      이해가 되셨다니 다행입니다.

  2. Dear Mr.Moon Young-IL,
    why does the kernel need HIGHMEM zone on 32 bits system? and why doesn’t the kernel use 1:1 map directly as in 64 bits system?

  3. First, let’s look at the biggest features of normal and highmem zones.

    1) normal zone
    – Use a portion of kernel space to map the physical memory in advance so that the kernel can quickly allocate memory.
    – The normal zone has limited space and is used first for kernel memory allocation.

    2) highmem zone
    – Physical memory is larger than the kernel virtual address space and can not be pre-mapped. The area exceeding this is called highmem zone.
    – Unlike kernel memory allocation, when user memory allocation is used, always use physical memory in user space. At this time, the physical memory located in the highmem zone is used first. If this highmem zone is exhausted, the normal zone is used.

    Let’s look at the difference between a 64-bit system and a 32-bit system for the normal zone.

    64bit
    – A very large virtual address space is given on 64-bit systems.
    – ARMv8 architecture with 64 bit ARM is given a maximum of 256T virtual address space for kernel purposes.
      You can use half 128T space as a normal zone.
    – Since all this huge physical memory can be accessed from kernel memory, there is no need to separate them by separate highmem zone.

    – 32bit ARM
    – The maximum virtual address space available on a 32-bit system is 4G.
    – Use 1G, which is 1/4 of the kernel size (adjustable kernel configuration) as the kernel space.
    – Use a space of several hundreds mega bytes as a normal zone, excluding some in 1G space.
    – All memories exceeding normal zone are separated into highmem zone.

    Thanks,

    ————————————————————————————

    먼저 normal zone과 highmem zone의 가장 큰 특징을 알아보겠습니다.

    1) normal zone
    – 커널에서 메모리를 빠르게 할당할 수 있도록 커널 공간의 일부를 사용하여 미리 물리 메모리를 매핑하여 사용한다.
    – normal zone은 공간이 제한되어 있어 커널 메모리 할당에 우선 사용됩니다.

    2) highmem zone
    – 물리 메모리가 커널 가상 주소 공간보다 더 커 미리 매핑되지 못하는 공간이다. 이 초과하는 영역을 highmem이라고 한다.
    – 커널 메모리 할당과 다르게 유저 메모리 할당을 이용하는 경우 항상 유저 공간에 물리 메모리를 매핑하여 사용합니다. 이 때 우선적으로 highmem zone에 위치한 물리 메모리를 사용합니다. 이 highmem zone을 모두 소모하는 경우 normal zone이 사용됩니다.

    그 다음 normal zone에 대한 64비트 시스템과 32비트 시스템의 차이를 알아보겠습니다.

    64bit
    – 64bit 시스템에서는 아주 큰 가상 주소 공간이 주어집니다.
    – 64 bit ARM인 ARMv8 아키텍처는 커널 용도로 최대 256T 가상 주소 공간이 주어집니다.
    그 중 절반 128T 공간을 normal zone으로 사용할 수 있습니다.
    – 이렇게 아주 큰 물리 메모리를 모두 커널 메모리에서 접근가능하므로 별도의 highmem 영역을 두어 따로 구분할 필요 없습니다.

    – 32bit ARM
    – 32bit 시스템에서 사용할 수 있는 최대 가상 주소 공간의 크기는 4G 입니다.
    – 그 중 1/4(대부분 커널이 사용하는 커널 설정)인 1G를 커널 공간으로 사용합니다.
    – 1G 공간에서 일부를 제외한 수백M의 공간을 normal zone으로 사용합니다.
    – normal zone을 초과하는 메모리들은 모두 highmem zone으로 분리합니다.

    (끝)

    1. Thank you for your quick response. I have a recommendation for you that texts and message in the pictures should be commented in english. Because I can not read and understand Korea language well.

      1. Thank you for your quick response. I have a good idea for you. Because I can not read and understand Korea language well. so you can write articles in english. if true, thank you so much.

  4. Thank you for your feedback. When I first tried to write a blog, I thought I would write it in English. I’ll try it someday.

  5. 글들 볼때마다 깊이감과 이해감에 존경스럽습니다 글 잘 보고 커널공부 하고 있습니다 !!! 좋은글 감사합니다.

  6. 안녕하세요 zone에 대해서 고질적으로 이해가 안되는 부분이 있어 질문드립니다.

    1. 물리 메모리공간의 크기가 DMA 디바이스가 접근할 수 있는 주소공간이면 ZONE_DMA또는 ZONE_DMA32를 별도로 지정하지 않는다는 것으로 이해했습니다. 그런데 예를 들어 x86-64bit 환경에서 6GB의 물리 메모리 공간이 있다면, ZONE_DMA32가 필요하게 되고, 이 ZONE_DMA32는 4GB크기로 고정되는 것으로 보이는데, 이런 경우에 ZONE_NORMAL로 사용할 수 있는 영역은 나머지 2GB인가요? 그럼 전체 6GB 메모리 중에서 커널이 kmalloc()하여 사용할 수 있는 영역의 크기는 2GB밖에 되지 않는게 맞나요?

    2. ZONE_DMA, ZONE_NORMAL, ZONE_HIGHMEM 모두 가상주소공간에서 커널 주소 영역이 물리메모리에 어떻게 매핑되는가를 설명하고 있는데, 유저 프로세스 주소 영역(예를 들어 4GB 가상주소공간에서 커널이 상위 1GB, 유저프로세스가 하위 3GB를 사용한다면)은 어느 zone에 매핑되는 것인가요?

    너무 기본적인 질문 같기도 한데 존의 개념자체가 와닿지 않아 아무리봐도 이해가 되지않네요.
    그리고 항상 좋은 블로그 글들 감사드립니다!

  7. 안녕하세요?

    1. 6G 메모리 중 ZONE_NORMAL에 사용되는 것이 2G 맞습니다.
    ZONE_DMA, ZONE_DMA32, ZONE_NORMAL 모두 kmalloc() 같은 커널 메모리 할당자를 사용하여 사용할 수 있습니다.
    다만 가급적 normal -> dma32 -> dma 순으로 메모리를 할당합니다.

    2. 가상 공간은 프로세스 수 만큼 많습니다. 10개의 프로세스를 동작시키면 가상 공간이 4G(32bit 기준) x 10개가 되겠죠.
    이 가상 공간들의 3G 영역 중 프로세스가 사용한 만큼만 물리 메모리를 할당하여 사용합니다.
    그 중 highmem을 우선 할당하여 사용합니다.
    부족한 경우 normal, dma 순으로 할당합니다.
    또한 가상 공간 중 커널이 사용하는 1G 영역은 모든 프로세스와 공유되는 공간으로 설계되고,
    커널이 normal, dma 순으로 메모리를 할당하여 사용합니다. ( kmalloc() 등으로 highmem을 사용하지 않습니다.)

    참고로 zone은 물리 메모리 영역에 대해 속도 및 접근 제한 등의 이유로 나누어 관리합니다.

    감사합니다.

  8. 안녕하세요,
    좋은 정보 감사합니다.

    여태까지 메모리 Zone을 나누는 것은 커널 메모리에만 국한된 건줄 알았는데, 댓글 문의 중 유저 스페이스영역에 대한 메모리 할당은 highmem, normal, dma 순으로 할당된다고 나와 있네요.
    그렇다면 highmem이 없는 64bit의 경우, 유저 스페이스에서 사용하는 메모리는 normal 존에서 할당되나요? normal zone은 virtual memory와 physical memory가 directly mapping되어 있는데 각 프로세스마다 개별 주소공간(0x0000 — 0x max)을 어찌 제공하는지 궁금합니다.

    1. 안녕하세요?

      highmem이 없는 64bit OS의 경우 normal -> dma32 -> dma 순으로 할당합니다.
      arm64의 경우 메모리가 4G 이하인 경우 커널 config 옵션에 따라 normal 또는 dma32 하나를 사용할 것입니다.

      normal을 포함한 그 아래의 존들은 커널 가상 주소 영역에 1:1로 프리 매핑되어 있어, 메모리 할당 시 곧바로 액세스가 가능합니다.
      그리고 이 영역들의 free 메모리 영역들은 각 유저 영역에서 메모리 요청을 할 때 vma 형태로 영역을 구분해 놓고,
      실제 해당 영역에 접근할 때 fault가 발생한 이 후 lazy allocation을 하며 이 때 해당 유저 가상 주소 영역에 매핑합니다.
      따라서 유저 영역에 매핑된 물리 메모리의 경우 커널 영역에도 매핑되어 있으므로 이중 매핑된 상태입니다.

      그 뿐 아니라 유저 영역에서 사용하는 glibc 같은 공유 라이브러리들은 여러 개의 유저 영역 수 만큼 추가 매핑되어 사용됩니다.

      감사합니다.

      1. 와… 지식의 깊이에 감탄하고 갑니다….
        저도 열심히 찾아봤지만 유저 메모리에 이중 매핑이 되어 있다는 얘기는 못본 것 같아요…
        그렇다면 정리하면 커널 가상메모리는 모든 물리메모리에 1:1 맵핑이 되어 있고 유저 가상메모리에서 page fault를 통해 할당하는 물리메모리의 경우, 실제로는 유저 가상메모리와 커널 가상메모리 두 개다에 맵핑이 되어 있다는 말씀이시네요.
        감사합니다.!

  9. 안녕하십니까,

    ZONE_NORMAL에 대하여 본문에서 다음과 같이 말씀을 해주셨는데,
    ‘시스템에서 지원하는 물리 메모리가 아키텍처의 가상 주소에 ‘
    1:1로 미리 매핑되어 있다는 부분이 명확히 이해가 안되어 질문을 드립니다..

    질문:
    ‘1:1로 미리 매핑’ 이라는 것은 ZONE_NORMAL 물리 메모리에 대한 페이지 테이블을 미리 전부 구성 해놓은 것이라고 보면 될까요??
    예를 들어, 커널 가상 주소 공간이 0에서 시작을 한다고 가정을 한다면.. arm64 아키텍처 / 8GB 메모리를 전부 ZONE_NORMAL로 구성한 경우
    가상 주소 공간 0x00_00000000 ~ 0x01_FFFFFFFF 에 해당하는 페이지 테이블이 미리 구성되어 있는 것이 맞을까요??

    1. 네. 맞습니다. 말씀하신것 처럼 가상 주소가 0부터 시작한다고 보면, 8G 메모리 전부가 NORMAL_ZONE이고
      이를 0x00_00000000 ~ 0x01_FFFFFFFF 가상 주소 공간에 모두 매핑합니다.

      물론 실제 매핑되는 커널 주소 공간은 다음과 같습니다.
      (예: VA_BITS=48을 사용하는 커널 주소 공간 – 0xFFFF0000_00000000 ~ 0xFFFF0001_FFFFFFFF)

      감사합니다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다