2014년 4월 20일 일요일

[Linux Kernel] 51주차(2014.04.19) 후기

10차 ARM 리눅스 커널 스터디 51주차(2014.04.19) 후기입니다.

일시 : 2014.04.19 (51주차)

모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C

장소 : 토즈 타워점

장소지원 : NAVER 개발자 커뮤니티 지원 프로그램

참여인원 : 5명

스터디 진도 :

  • start_kernel()-> mm_init()->mem_init()
  • ostart_kernel()-> mm_init()->kmem_cache_init() 분석중

스터디관련 내용

buddy할당자에 이어서 kmem 할당자 (slub)을 분석중입니다. 스터디를 시작한지 1년이 되었습니다. 함께 해주셨던 모든 분들 정말 수고하셨습니다. 다음주(52주차)는 스터디 1년을 기념하는 조촐한 저녁을 함께 하기로 하였습니다. 아울러 그 다음주 5월 1주(53주차)는 가족과 함께 하기로 하였습니다.

mem_init();

bootmem으로 관리하던 메모리를 buddy할당자로 이관합니다. 그리고 각 section이 사용하는 메모리의 크기를 출력합니다.

free_hot_cold_page() 에서 cold 와 hot의 의미?

cold 변수가 1 이면 (cold) 리스트의 마지막에 붙여 천천히 리스트에서 검색되도록 하며 0 이면 (hot) 리스트의 처음에 붙여 빨리 검색되어 사용되도록 한다.

mem_init_print_info()

.init.* 는 .data 섹션으로 바꿔 주는 과정이다. .rodata.* 는 .text나 .data섹션으로 바꿔준다.

BUILD_BUG_ON

char[-1]이면 컴파일시 에러가 발생해서 개발자가 알수 있게 함.

PKMAP Persistent Kernel Map

a Space is reserved at the top of the kernel page tables from PKMAP_BASE to FIXADDR_START for a PKMap

free_highpages();

  • max_low = max_low_pfn + PHYS_PFN_OFFSET;
    • max_low_pfn : 0x2f800
    • PHYS_PFN_OFFSET : 0x20000
    • max_low : 0x4f800
  • for_each_memblock(memory, mem) {
       define for_each_memblock(memblock_type, region)        \
      for (region = memblock.memblock_type.regions;        \
      region < (memblock.memblock_type.regions + memblock.memblock_type.cnt);    \
       region++)
    
    • for ( mem = memblock.memory.regions; \
       mem < (memblock.memory.regions + memblock.memory.cnt);    \
       mem++)
      
      • memblock.memory.regions
        • struct memblock { phys_addr_t current_limit; struct memblock_type memory; struct memblock_type reserved; };
      • memblock.memroy.regions[0].base : 0x2000 0000
      • memblock.memroy.regions[0].size : 0x8000 0000
  • start : memblock_region_memory_base_pfn(mem) : 0x20000
  • end : memblock_region_memory_end_pfn(mem) : 0xa0000
  • if (end <= max_low)
    • end : 0xa0000 <= max_low : 0x4f800
  • if (start < max_low)
    • start : 0x20000 < max_low : 4f8000
    • srtat = max_low : 0x4f800
  • for_each_memblock(reserved, res) {
    • for ( res = memblock.reserved.regions; \
       res < (memblock.reserved.regions + memblock.reserved.cnt);    \
       res++)
      
    • res_start = memblock_region_reserved_base_pfn(res); 0x50000 (pfn)으로 가정
    • res_end = memblock_region_reserved_end_pfn(res); 0x50100 (pfn)으로 가정
    • if (res_start != start)
    • res_start : 0x50000 , start : 0x4f800
  • free_area_high()
    • pfn : 0x4f800, end : 0x50000 으로 가정
    • free_highmem_page(pfn_to_page(pfn));
    • order 0으로 buddy에 추가.
  • mem_init_print_info()
    • .init.* 는 .data 섹션으로 바꿔 주는 과정이다.
    • .rodata.* 는 .text나 .data섹션으로 바꿔준다.
  • vector : CONFIG_VECTORS_BASE : 0xffff0000 - PAGE_SIZE : 0x1000
    • 0xffff1000 - 0xffff0000 : 4 kB
    • UL(x) : xUL
  • TASK_SIZE : 0xBF8000000 , MODULES_VADDR: 0xBF000000: 0xC0000000 (3GB) - 0x01000000 (16MB)
  • BUILD_BUG_ON
    • char[-1]이면 컴파일시 에러가 발생해서 개발자가 알수 있게 함.
  • PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > PAGE_OFFSET
    • // PAGE_OFFSET: 0xC0000000, PMD_SIZE: 0x00200000
    • // PKMAP_BASE : 0xBFE00000
    • // LAST_PKMAP : PTRS_PER_PTE : 512
    • // PAGE_SIZE : 0x1000 (4kB)
  • oif (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) {
    • PAGE_SIZE : 4096 , 16k이상 이면 NG,
    • physical : 512k

slab slub. slob

slab 할당자는 주어진 객체의 크기에 따라 커널의 buddy system으로부터 적당한 수의 페이지를 할당받고 이를 하나로 묶어 여러 객체를 저장할 수 있는 단위로 관리하는데 이것이 바로 slab이다. slab 할당자는 많은 캐시와 (그에 따른) 메타 정보를 필요로하기 때문에 적지 않은 양의 메모리를 단지 slab을 관리하기 위한 용도로 낭비(?)하게 된다.
slub 할당자는 이러한 낭비를 없애 메모리 활용을 더욱 효율적으로 하기 위해 개발되었으며 slab 할당자와 동일한 API를 제공하므로 단지 커널 빌드 시 slub을 사용하도록 선택하였다면 아무런 소스 변경 없이 곧바로 slub 할당자를 이용할 수 있다. slub으로 할당된 객체들은 동일 slub 내의 다음 (free) 객체에 대한 포인터를 직접 포함한다. 이는 RCU, 생성자(ctor), 디버깅 기능 사용 유무에 따라 객체 내에 있을 수도 있고 밖에 있을 수도 있다. 페이지 내의 이용 가능한 첫 객체는 page 구조체 내의 freelist 필드가 가리키도록 하였다. slub의 메타 정보들은 모두 page 구조체 내에 포함되어 있으므로 별도의 메모리를 낭비하지 않는다.
slob은 이러한 slub의 overhead마저도 부담스러운 경우 사용할 수 있는데 페이지를 작은 단위(SLOB_UNIT)로 나누고 이를 블럭으로 묶어 할당을 수행한다. (페이지 크기에 따라 다르지만 대부분의 경우 SLOB_UNIT은 2 바이트 크기의 구조체이다.)

Slab, slub, slob 은 KERNEL의 CONFIG으로 설정

우리는 KERNEL CONFIG으로 Slub을 사용한다. mm/Makefile에서 CONFIG_SLUB 설정으로 slub.c로 이동합니다.

create_boot_cache()

slab(slub) 서비스가 시작되지 않았기 때문에 캐쉬를 생성하는 과정입니다.

스터디 로그

68317b1..a07195b  master     -> origin/master
Updating 68317b1..a07195b
Fast-forward
 arch/arm/include/asm/bitops.h         |   2 +
 arch/arm/include/asm/cache.h          |   5 ++
 arch/arm/include/asm/highmem.h        |   3 +
 arch/arm/include/asm/memory.h         |   4 +
 arch/arm/include/asm/page.h           |   1 +
 arch/arm/include/asm/pgtable-2level.h |   1 +
 arch/arm/include/asm/spinlock_types.h |   2 +
 arch/arm/mm/init.c                    |  52 +++++++++++--
 include/asm-generic/atomic-long.h     |   1 +
 include/asm-generic/bug.h             |   1 +
 include/asm-generic/getorder.h        |   6 ++
 include/linux/bug.h                   |   1 +
 include/linux/cache.h                 |   4 +-
 include/linux/gfp.h                   |   1 +
 include/linux/log2.h                  |   2 +
 include/linux/memblock.h              |   9 +++
 include/linux/mm.h                    |  14 +++-
 include/linux/mmzone.h                |   2 +
 include/linux/nodemask.h              |   1 +
 include/linux/page-flags.h            |   1 +
 include/linux/pfn.h                   |   2 +
 include/linux/slab.h                  |   8 +-
 include/linux/slub_def.h              |   2 +
 include/linux/spinlock_types.h        |   6 +-
 include/linux/types.h                 |   4 +
 include/uapi/linux/const.h            |   2 +
 include/uapi/linux/mman.h             |   1 +
 init/main.c                           |   5 ++
 mm/highmem.c                          |   4 +-
 mm/page_alloc.c                       |  20 ++++-
 mm/slab.h                             |  10 ++-
 mm/slab_common.c                      |  24 +++++-
 mm/slub.c                             | 171 ++++++++++++++++++++++++++++++++++++++++---
 33 files changed, 344 insertions(+), 28 deletions(-)

댓글 없음:

댓글 쓰기