티스토리 뷰

4-101, 102

kswapd 는 페이지를 회수하는데, watermark_high 보다 올라가면 잠들고, low 보다 낮아지면 깨어나서 회수를 시작한다.

min_free_kbytes 보다 높아질때까지 kswapd 는 메모리를 확보하고, min 보다 낮아지는 경우는 kswapd 에 의존하기만 하지 않고, 직접 페이지 수행을 시도해본다

page_alloc.c __zone_watermark_ok

alloc_harder = highautomic 용도로 사용되는 reserve 페이지 블록에서도 할당
free_pages 로 들어온 인자는 밖에서 zone_page_stage(z_ NR_FREE_PAGES)) 로 넘어온 값


min = ? 여기에서 min 의 의미가 뭘까? -> 할당 성공률을 높인다고는 하는데,,
min = mark 로 사용했는데, alloc 시 WATER_MARK FLAG 에 따라서 워터마크에 설정된 값이 들어옴. (min,low,high, or none 에 따라?)
그러므로 min 같은걸 설정했으면 더 작은수가 들어왔을 것.

if (free_pages <= min + z->lowmem_reserve[classzone_idx])
    return false;
그러니까 이것의 의미는, 내가 할당을 수행하고 나면 남는 페이지 수가 워터마크 이하로 떨어지는 경우 워터마크에서 허락하지 않겠다.

오더가 큰 경우는 버디에 해당 오더의 페이지가 있는지 확인해야 한다. -> 회수를 진행하지 않았을때 머지가 안된 상태이고. 더 높은 오더의 페이지가 있다면 쪼개서 사용할 수 있으니

근데 high atomic 은 왜 검사 안해주냐?
-->
    if (likely(!alloc_harder))
        free_pages -= z->nr_reserved_highatomic;
alloc harder 가 아닐때는 여기서 이미 뺐기땜문!@!!@!@ / alloc harder 일때는 min 을 줄였음

    if (alloc_harder)
        return true;
       --> migrate 타입 검사 안하고 트루 해버림

4-103

init_per_zone_wmark_min

nr_free_buffer_pages -> water mark high 이상의 페이지 수를 줌.
 --> ZONE_HIGHMEM, ZONE_NORMAL, ZONE_DMA 모두 각자 HIGH 워터마크가 있는거였는데, HIGHMEM 이랑 헷갈렸었따.
 --> ZONE_NORMAL 이하에서 water mark high 이상을 뺀 페이지 수를 구했던 것

gpt: nr_free_buffer_pages 함수는 특정 워터마크 기준(WMARK_HIGH)보다 여유가 있는 페이지 수를 반환합니다. 이 값은 현재 사용 가능한 메모리 양이 워터마크에 대해 얼마나 안정적인지를 나타내는 지표로 볼 수 있습니다.

lowmem_kbytes -> node 에서 계산되고, 이걸 가지고 각 zone 에서 처리 되는걸로 보임

여기서 10 씩 >> 땡긴게 kbytes 라 그렇구나

4-104

__setup_per_zone_wmarks

zone 은 아래 페이지 타입을 갖고 있었음
    unsigned long        managed_pages;
    unsigned long        spanned_pages;
    unsigned long        present_pages;

이중에 lowmem_pages 는 managed_pages 를 합산해서 사용함. 근데 저 페이지들이 뭔지 까먹었음.

spanned_pages = zone_end_pfn - zone_start_pfn; -> 전체
present_pages = spanned_pages - absent_pages(pages in holes); -> hole 제거
managed_pages = present_pages - reserved_pages; -> reserved pages 제거인데 reserved 가 뭐더라

        tmp = (u64)pages_min * zone->managed_pages;
        do_div(tmp, lowmem_pages);
-> zone 의 managed_pages 비율만큼 중에서 pages_min 곱한만큼 가져감

highmem 인 경우는 아주 작게 설정하는 걸로 보임

tmp 가 MIN 까지는 비율로 바로 처리했었음. 여기서 scale_factor 를 적용하는 값으로 LOW, HIGH 를 구함

tmp >> 2 로 4로 나눴으니 25% 로 줄인 값과  watermark_scale_factor 에 따라 결정된 값을 max

4-105

calculate_totalreserve_pages

모든 node 의 모든 zone 을 순회 한다. 

watermark 의 비율은 ZONE_HIGHMEM 를 제외하고는 비율에 따라 된거고

lowmem_reserve -> 다른 zone 꺼의 lowmem 을 미리 예약해둔건가? 이중에 max 를 찾아서 reserve 로 처리하고있음

근데 아직 잘모르겠다.
gpt: memblock의 lowmem은 시스템 부팅 시 사용 가능한 저메모리 영역을 관리하는 반면, zone의 lowmem_reserve는 이미 예약된 페이지 수를 관리하여 시스템 메모리의 안정성을 높이는 데 초점을 맞추고 있습니다.

4-106, 4-107

refresh_zone_stat_thresholds

원래는 존과 각 cpu 의 카운터를 다 더해야 하는데, 성능상 아까우니까 thresholds 보다 크면 대충 계산하겠다.

모든 zone 을 순회해서, 해당 zone 의 threshold 를 계산한다.

tolerate = 참을 수 있는 수준
max = 최대치

fls -> find last set bit

이게 맞아?
Gpt: 이 조건문은 max_drift가 tolerate_drift보다 클 경우, 즉 모든 CPU가 동시에 요구할 수 있는 최대 메모리량이 현재 존에서 수용할 수 있는 여유 공간보다 클 때를 체크합니다.

4-108

setup_per_zone_lowmem_reserve

일단 자기 zone 이 자기를 가리키는 lowmem_reserve 를 0으로 초기화

그리고 자기 아래 zone 들에 대해 (normal 이었다면 dma 에 대해, high 였다면 normal dma 에 대해)

해당 zone 의 lowmem_reserve_ratio 만큼을 내 managed_pages 에 적는다.  아 그러니까 normal 이었다면 dma 영역도 쓸 수 있다는 뜻인듯. 그래서 managed_pages 에 lower_zone 의 managed_pages 를 점점 추가함

409 page

setup_per_zone_inactive_ration

mangaed_pages 에 따라 inactive anon 페이지 비율을 정하는데, 이게 뭐 실제 비율도아니고 그냥 페이지 수에따라 비율이 정해지는데 이게 왜필요한거지?

gpt: 메모리 압박 감지: 시스템에서 메모리 사용량이 증가하고, 비활성 익명 페이지가 부족할 때 이 함수가 호출됩니다
일정 비율보다 떨어지면 필요한 페이지를 가져와야 하나보다

inactive_anon_is_low_global
inactive_anon_is_low

check if anonymous pages need to be deactivated

4.7 슬랩 할당자

  • 슬랩, 슬럽, 슬롭 중 하나를 선택
  • 여기서는 슬럽을 기준으로 알아보자

사용중인 객체 / 빈 객체 (free)

빈 객체는 서로 FreePointer (FP) 를 통해 연결

kmem_cache 는 커널 메모리 슬랩 캐시의 약자.

4-109

kmem_cache_init

boot_kmem_cache -> kmem_cache 라는 구조체를 슬랩 객체로 할당해주기 위한 슬랩 캐시
boot_kmem_cache_node -> kmem_cache_node 라는 구조체를 슬랩 객체로 할당하기 위한 슬랩 캐시

근데 둘다 kmem_cache 구조체로 만들어졌음!!!!

static __initdata struct kmem_cache boot_kmem_cache, boot_kmem_cache_node;

void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t size,
        unsigned long flags)

4-110, 4-111

create_boot_cache

kmem_cache 에 값을 설정. 그러나 kmem_cache 의 정확한 용도는 파악이 되지 않은 상태

object 의 사이즈와 align 을 설정 (hardware align 의 경우 default 는 L1 cache bytes (8k~64k)

gpt: 캐시 바이트 사이즈와 데이터 캐시라인 크기는 다른 정의
- 정의: 캐시 바이트 사이즈는 전체 캐시 메모리 용량을 의미하며, 캐시에 저장할 수 있는 데이터의 총 양입니다.
- 일반적으로 L1 데이터 캐시의 캐시 라인 크기는 64바이트입니다.

mcg: Memory Resource Controller. 메모리 접근 가능에 대한 설정인듯?
memcg_params 을 설정
RCU_INIT_POINTER -> Read Copy Update 포인터??

__kmem_cache_create(s, flags); // flags = SLAB_HWCACHE_ALIGN

4-112

bootstrap

kmem_cache (전역) = &boot_kem_cache
bootmem 으로 만들었던 kmem_cache 를 memcpy 로 복사함. object size 만큼 복사하는걸 보니 딱 하나만 있던 상태

IPI(Inter-Processor Interrupt)는 Inter-Processor Interrupt의 약자로, 다중 프로세서 시스템에서 하나의 CPU가 다른 CPU에게 특정 작업을 수행하라고 요청하는 인터럽트

gpt: smp_processor_id는 Linux 커널에서 현재 실행 중인 CPU의 ID를 반환하는 함수입니다. SMP(대칭 멀티 프로세싱) 시스템에서 각 CPU는 고유한 ID를 가지며, smp_processor_id 함수를 통해 현재 코드를 실행 중인 CPU의 ID를 확인할 수 있습니다.

그러니까 내 로컬 cpu 에서 slab 캐스를 플러시한다는 뜻인가?

4-113

setup_kmalloc_cache_index_table

  • 사이즈에 따라 배열에 값을 지정하는데, 그림 4-80 은 초기 배열의 상태이고, 4-81 은 setup_kmalloc_cache_index_table 을 실행하면 저렇게 바뀜

min 사이즈가 작을때 넣어놨던 최적화 코드가 사이즈가 크다면 쓸 필요 없으니 없앰

댓글