Linux 메모리 관리 (Linux 커 널 깊이 이해)
물리 적 메모리 중 일 부 는 커 널 에 계속 (Permanently) 매 핑 되 어 사 용 됩 니 다. 이 부분 은 커 널 의 코드 와 커 널 의 정적 데이터 구조 체 를 저장 하 는 데 사 용 됩 니 다.이러한 물리 적 메모 리 를 커 널 에 계속 비 추 려 는 이 유 는 이러한 내용 (코드, 정적 데이터 구조) 이 전체 운영 체제 가 실행 되 는 과정 에서 끊임없이 인용 되 어야 하기 때 문 입 니 다. 물리 적 메모리 에 있 는 위 치 를 동적 으로 분배 하고 번역 하 는 방식 으로 유지 하려 면 CPU 시간 이 너무 많이 걸 립 니 다.
이런 방식 은 공간 으로 시간 을 바 꾸 는 전략 으로 이해 할 수 있다.
물리 메모리 의 나머지 부분 은 동적 메모리 입 니 다.
동적 메모 리 는 사용자 상태의 각 프로 세 스 에 필요 할 뿐만 아니 라 커 널 자체 도 필요 합 니 다.
Page Frame Management
Memory Area Management
물리 적 으로 연 결 된 메모리 영역 을 관리 하 는 두 가지 방식 입 니 다.
Noncontiguous Memory Area Management
물리 적 으로 연결 되 지 않 는 물리 적 메모리 영역 을 처리 하 는 방식 입 니 다.
Page Descriptor
커 널 은 모든 페이지 의 현재 상 태 를 유지 해 야 합 니 다.
예 를 들 어 어떤 물리 페이지 가 현재 누가 사용 하고 있 는 지 구분 할 수 있어 야 한다.
1. 사용자 상태의 프로 세 스
2. 커 널 코드
3. 내부 핵 상태의 데이터 구조
마찬가지 로 Dynamic Memory 에서 분 배 된 물리 적 메모리 페이지 가 현재 어떤 상태 에 있 는 지 구분 할 수 있어 야 합 니 다.
1. 석방 상태
2. 사용자 상태의 프로 세 스 데 이 터 를 저장 합 니 다.
3. 소프트웨어 하 나 를 저장 하 는 Cache
4. 동적 분 배 를 저장 하 는 커 널 의 데이터 구조
5. 장치 가 구동 하 는 캐 시 데 이 터 를 저장 합 니 다.
6. 커 널 모듈 을 저장 하 는 코드
각 페이지 의 설명 구조 체 는 하나의 struct page 의 인 스 턴 스 로 저 장 됩 니 다. 이 인 스 턴 스 는 mem 에 저 장 됩 니 다.맵 배열 중.
각 struct page 크기 는 32 바이트 이기 때문에 약 1% (32 / 4096) 의 물리 적 메모 리 를 사용 하여 이 배열 을 저장 합 니 다.
커 널 은 페이지 구조 체 의 위 치 를 얻 기 위해 다음 과 같은 매크로 를 제공 합 니 다.
1: #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
2:
3: /*
4: * supports 3 memory models.
5: */
6: #if defined(CONFIG_FLATMEM)
7:
8: #define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
9: #define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + \
10: ARCH_PFN_OFFSET)
11: #elif defined(CONFIG_DISCONTIGMEM)
12:
13: #define __pfn_to_page(pfn) \
14: ({ unsigned long __pfn = (pfn); \
15: unsigned long __nid = arch_pfn_to_nid(__pfn); \
16: NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\
17: })
18:
19: #define __page_to_pfn(pg) \
20: ({ struct page *__pg = (pg); \
21: struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg)); \
22: (unsigned long)(__pg - __pgdat->node_mem_map) + \
23: __pgdat->node_start_pfn; \
24: })
25:
26: #elif defined(CONFIG_SPARSEMEM_VMEMMAP)
27:
28: /* memmap is virtually contiguous. */
29: #define __pfn_to_page(pfn) (vmemmap + (pfn))
30: #define __page_to_pfn(page) (unsigned long)((page) - vmemmap)
31:
32: #elif defined(CONFIG_SPARSEMEM)
33: /*
34: * Note: section's mem_map is encorded to reflect its start_pfn.
35: * section[i].section_mem_map == mem_map's address - start_pfn;
36: */
37: #define __page_to_pfn(pg) \
38: ({ struct page *__pg = (pg); \
39: int __sec = page_to_section(__pg); \
40: (unsigned long)(__pg - __section_mem_map_addr(__nr_to_section(__sec))); \
41: })
42:
43: #define __pfn_to_page(pfn) \
44: ({ unsigned long __pfn = (pfn); \
45: struct mem_section *__sec = __pfn_to_section(__pfn); \
46: __section_mem_map_addr(__sec) + __pfn; \
47: })
48: #endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */
49:
50: #define page_to_pfn __page_to_pfn
51: #define pfn_to_page __pfn_to_page
페이지 구조 체
1: /*
2: * Each physical page in the system has a struct page associated with
3: * it to keep track of whatever it is we are using the page for at the
4: * moment. Note that we have no way to track which tasks are using
5: * a page, though if it is a pagecache page, rmap structures can tell us
6: * who is mapping it.
7: */
8: struct page {
9: unsigned long flags; /* Atomic flags, some possibly
10: * updated asynchronously */
11: atomic_t _count; /* Usage count, see below. */
12: union {
13: /*
14: * Count of ptes mapped in
15: * mms, to show when page is
16: * mapped & limit reverse map
17: * searches.
18: *
19: * Used also for tail pages
20: * refcounting instead of
21: * _count. Tail pages cannot
22: * be mapped and keeping the
23: * tail page _count zero at
24: * all times guarantees
25: * get_page_unless_zero() will
26: * never succeed on tail
27: * pages.
28: */
29: atomic_t _mapcount;
30:
31: struct { /* SLUB */
32: u16 inuse;
33: u16 objects;
34: };
35: };
36: union {
37: struct {
38: unsigned long private; /* Mapping-private opaque data:
39: * usually used for buffer_heads
40: * if PagePrivate set; used for
41: * swp_entry_t if PageSwapCache;
42: * indicates order in the buddy
43: * system if PG_buddy is set.
44: */
45: struct address_space *mapping; /* If low bit clear, points to
46: * inode address_space, or NULL.
47: * If page mapped as anonymous
48: * memory, low bit is set, and
49: * it points to anon_vma object:
50: * see PAGE_MAPPING_ANON below.
51: */
52: };
53: #if USE_SPLIT_PTLOCKS
54: spinlock_t ptl;
55: #endif
56: struct kmem_cache *slab; /* SLUB: Pointer to slab */
57: struct page *first_page; /* Compound tail pages */
58: };
59: union {
60: pgoff_t index; /* Our offset within mapping. */
61: void *freelist; /* SLUB: freelist req. slab lock */
62: };
63: struct list_head lru; /* Pageout list, eg. active_list
64: * protected by zone->lru_lock !
65: */
66: /*
67: * On machines where all RAM is mapped into kernel address space,
68: * we can simply calculate the virtual address. On machines with
69: * highmem some memory is mapped into kernel virtual memory
70: * dynamically, so we need a place to store that address.
71: * Note that this field could be 16 bits on x86 ... ;)
72: *
73: * Architectures with slow multiplication can define
74: * WANT_PAGE_VIRTUAL in asm/page.h
75: */
76: #if defined(WANT_PAGE_VIRTUAL)
77: void *virtual; /* Kernel virtual address (NULL if
78: not kmapped, ie. highmem) */
79: #endif /* WANT_PAGE_VIRTUAL */
80: #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS
81: unsigned long debug_flags; /* Use atomic bitops on this */
82: #endif
83:
84: #ifdef CONFIG_KMEMCHECK
85: /*
86: * kmemcheck wants to track the status of each byte in a page; this
87: * is a pointer to such a status block. NULL if not tracked.
88: */
89: void *shadow;
90: #endif
91: };
1. flags, 현재 페이지 의 상 태 를 정의 하 는 enum 변 수 는 현재 페이지 가 있 는 zone 번호 (also encodes the zone number to which the page frame belongs) 도 저장 합 니 다.
그 중 각 상태의 정 의 는 다음 과 같다.
1: enum pageflags {
2: PG_locked, /* Page is locked. Don't touch. */
3: PG_error,
4: PG_referenced,
5: PG_uptodate,
6: PG_dirty,
7: PG_lru,
8: PG_active,
9: PG_slab,
10: PG_owner_priv_1, /* Owner use. If pagecache, fs may use*/
11: PG_arch_1,
12: PG_reserved,
13: PG_private, /* If pagecache, has fs-private data */
14: PG_private_2, /* If pagecache, has fs aux data */
15: PG_writeback, /* Page is under writeback */
16: #ifdef CONFIG_PAGEFLAGS_EXTENDED
17: PG_head, /* A head page */
18: PG_tail, /* A tail page */
19: #else
20: PG_compound, /* A compound page */
21: #endif
22: PG_swapcache, /* Swap page: swp_entry_t in private */
23: PG_mappedtodisk, /* Has blocks allocated on-disk */
24: PG_reclaim, /* To be reclaimed asap */
25: PG_swapbacked, /* Page is backed by RAM/swap */
26: PG_unevictable, /* Page is "unevictable" */
27: #ifdef CONFIG_MMU
28: PG_mlocked, /* Page is vma mlocked */
29: #endif
30: #ifdef CONFIG_ARCH_USES_PG_UNCACHED
31: PG_uncached, /* Page has been mapped as uncached */
32: #endif
33: #ifdef CONFIG_MEMORY_FAILURE
34: PG_hwpoison, /* hardware poisoned page. Don't touch */
35: #endif
36: #ifdef CONFIG_TRANSPARENT_HUGEPAGE
37: PG_compound_lock,
38: #endif
39: __NR_PAGEFLAGS,
40:
41: /* Filesystems */
42: PG_checked = PG_owner_priv_1,
43:
44: /* Two page bits are conscripted by FS-Cache to maintain local caching
45: * state. These bits are set on pages belonging to the netfs's inodes
46: * when those inodes are being locally cached.
47: */
48: PG_fscache = PG_private_2, /* page backed by cache */
49:
50: /* XEN */
51: PG_pinned = PG_owner_priv_1,
52: PG_savepinned = PG_dirty,
53:
54: /* SLOB */
55: PG_slob_free = PG_private,
56:
57: /* SLUB */
58: PG_slub_frozen = PG_active,
59: };
그 중에서 커 널 은 조작 하기에 편리 한 매크로 를 정의 합 니 다.
1: PageXXX()
2:
3: SetPageXXX()
4:
5: ClearPageXXX()
각각 상태 위 치 를 조회, 설정, 제거 하 는 데 사 용 됩 니 다.
2. _count, 인용 계수
1: page_count()
인용 수 를 조회 하 는 데 사용 할 수 있 습 니 다.
The pool of Reserved Page Frames
보류 페이지 할당 풀
메모리 페이지 를 할당 할 때 두 가지 상태 가 발생 할 수 있 습 니 다.
1. 남 은 메모리 페이지 가 충분 하고 분배 가 즉시 성공 합 니 다.
2. 남 은 메모리 페이지 가 부족 합 니 다. 메모리 회수 (Memory Reclaiming) 를 해 야 합 니 다. 메모리 페이지 를 신청 하 는 커 널 제어 경로 (Kernel Control Path) 는 남 은 메모리 페이지 가 나타 날 때 까지 block 되 어야 합 니 다.
그러나 일부 Kernel Control Path 는 block 되 어 서 는 안 됩 니 다. 예 를 들 어:
1. 중 단 된 Handler 처리 중;
2. 관건 구역 에 있 는 코드 (Critical Section)
이 Kernel Control Path 는 메모리 페이지 를 신청 할 때 GFP 를 사용 해 야 합 니 다.ATOMIC 로 고 는 신청 이 block 에 의 해 이 루어 져 서 는 안 된다 는 것 을 나타 내 며 충분 한 메모리 페이지 가 없 으 면 바로 실패 하고 돌아 갑 니 다.
하지만 내 핵 은 가능 한 한 GFP 를 확보 해 야 합 니 다.ATOMIC 유형의 신청 은 정확하게 실 행 될 수 있 기 때문에 커 널 은 물리 적 메모리 페이지 를 일정 수량의 보존 하고 있 습 니 다. 이 메모리 페이지 는 저 메모리 상태 (Low - On - Memory) 조건 에서 만 GFP 를 제공 합 니 다.ATOMIC 사용.
보통 minfree_kbytes (이렇게 많은 KB) 의 메모 리 를 Pool 로 사용 합 니 다.
공식 을 통과 하 다
1: reserved_pool_size = floor(sqrt(16 * (ZONE_DMA + ZONE_NORMAL)))
계산 하고 128 ∼ 65536 KB 로 제한한다.
그리고 크기 에 따라 ZONE 에서DMA 및 ZONENORMAL 간 에 각자 보유 한 비율 을 분배 하 다.
Linux 커 널 이 직접 매 핑 할 수 있 는 선형 주소 범 위 는 3GB ~ 3GB + 896 MB 이다.
이 범위 내 물리 메모리 페이지 를 할당 하면 분 배 된 페이지 의 선형 메모리 주 소 를 직접 되 돌려 줄 수 있 습 니 다.그러나 분 배 된 물리 적 메모리 가 이 범위 내 에 있 지 않 으 면 해당 하 는 커 널 공간의 선형 주 소 를 직접 되 돌 릴 수 없 지만 페이지 구조 체 (struct page) 의 주 소 를 되 돌 릴 수 있 습 니 다. 모든 물리 적 메모리 페이지 의 페이지 구조 체 는 mem 에 저장 되 어 있 기 때 문 입 니 다.맵 중.
이러한 방식 의 제한 은 선형 주소 공간 3GB ~ 3GB + 896 MB 범위 밖의 메모 리 를 할당 할 경우 이 물리 적 메모리 페이지 를 선형 주소 의 맵 으로 다시 업데이트 해 야 한 다 는 것 이다. 즉, 페이지 표를 다시 설정 하 는 것 이다.
페이지 시트 에 대한 추가 작업 으로 인해 이 메모리 들 을 분배 하 는 것 이 고정 맵 의 그 부분 메모 리 를 분배 하 는 것 보다 효율 적 입 니 다.
고급 메모리 맵 참조:http://linux.chinaitlab.com/administer/831348.html
다음으로 전송:https://www.cnblogs.com/long123king/p/3497445.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.