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에 따라 라이센스가 부여됩니다.