Download presentation
Presentation is loading. Please wait.
1
12장 Memory Management CSLAB Park Se Won
2
Page struct page{ unsigned long flags; atomic_t _count;
atomic_t _mapcount; unsigned long private; struct address_space *mapping; pgoff_t index; struct list_head lru; void *virtual; }; 모든 물리적 페이지 관리용 페이지소유자 Userspace process Dynamic data Static kernel code Page cache
3
Page 형 ( type ) 이름 내용 unsigned long flags 페이지의 상태를 나타내는 플래그,
플레그 배열로 페이지 프레임이 속하는 지역 번호를 가진다. atomic_t _count 페이지의 참조 카운트. unsigned int _mapcount 주소 공간에 매핑되고 있는 수. 페이지 프레임을 참조하는 페이지 테이블 엔트리의 수. ( 없으면 -1 ) private 용도에 따라 제각기 다름 페이지를 사용하는 커널 구성 요소가 이용. ( ex. 버퍼 페이지의 경우 버퍼 헤드의 주소 ) 페이지가 사용하지 않는 것이라면 필드는 버디 시스템을 사용 spinlock_t u.ptl 페이지 테이블 엔트리 변경 시의 잠금용 struct address_space * mapping 파일 캐시로 사용되고 있을 때, 그 주소 영역의 구조체 pgoff_t index 페이지 단위의 파일 오프셋, 또는 스왑 영역의 인덱스 ( mapping이 스왑 캐시의 경우 ) 다른 용도와 함께 일부 커널 구성 요소가 사용한다. 예를 들어, 페이지 디스크 이미지나 익명 영역 내에서 페이지에 저장될 자료의 위치를 식별한다. 또는 스왑된 페이지 식별자를 저장. struct list_head lru LRU 리스트용 ( zone 구조체 헤드 ) 오랫동안 사용하지 않은 페이지의 이중 연결 리스트에 대한 포인터를 담는다. void * virtual kmap되어 있을 때의 가상 주소 페이지의 가상 주소를 나타낸다. 보통 이 값은 단순히 가상 메모리 상의 페이지 주소.' struct page{ unsigned long flags; atomic_t _count; atomic_t _mapcount; unsigned long private; struct address_space *mapping; pgoff_t index; struct list_head lru; void *virtual; };
4
Page 변수 내용 flag 페이지 상태 저장 Modify, Locking 등 각 비트별로 총 32가지 상태 저장 가능
<linux/page_flags.h>에 저장되어있음 _count 페이지 사용횟수 -1: 페이지 사용 안하는 중 Page_count() 함수 이용; 0: 페이지 사용 안하는 중 virtual 가상 메모리 상의 페이지 주소 NULL: 고정된 주소가 아닐 때, 동적으로 설정됨 struct page{ unsigned long flags; atomic_t _count; atomic_t _mapcount; unsigned long private; struct address_space *mapping; pgoff_t index; struct list_head lru; void *virtual; };
5
Page 플래그명 의미 PG_locked 페이지에 락이 되어 있다. 예를 들어 디스크 입출력 연산과 관련된 페이지이다.
페이지에 락이 되어 있다. 예를 들어 디스크 입출력 연산과 관련된 페이지이다. PG_error 페이지 전송 중 입출력 에러가 발생한다. PG_referenced 이 페이지를 최근에 접근하였다. PG_uptodate 디스크 입출력 에러가 발생하지 않고, 읽기 작업을 마친 후에 플래그를 설정한다. PG_dirty 페이지를 수정하였다. PG_lru 페이지가 활성 또는 비활성 페이지 리스트에 들어 있다. PG_active active 리스트에 연결되어 있다. PG_slab 페이지를 슬랩으로 사용한다. PG_highmem 페이지 프래임이 슬랩에 들어 있다. PG_checked EX2와 EX3 파일 시스템에서 사용하는 플래그이다. PG_arcjh_1 아키텍쳐 종속, i386에서는 미사용. PG_reserved 커널 코드용으로 예약했거나 사용할 수 없는 페이지 프레임이다. PG_writeback writepage 메소드에 의해 디스크에 쓰는 중이다. PG_nosave 시스템 일시 중지/재개를 위해 사용. PG_compound 페이지 프레임이 확장 페이징 매커니즘을 통해 처리된다. PG_swapcache 페이지가 스왑 캐시에 속한다. PG_mappedtodisk 페이지 내 모든 자료는 디스크에 할당된 블록에 해당한다. PG_reclaim 메모리 해지를 위해 페이지가 디스크에 쓰여 졌다고 표시한다 PG_nosave_free 시스템 일시 중지/재개를 위해 사용된다. PG_private 추가로 필요한 자료를 저장한다.
6
<linux/mmzone.h>에 정의
WHY -특정 메모리 주소로만 DMA 수행 가능 x86인 경우 ISA 장치는 메모리 앞부분 16MB만 접근 가능 PCI장치는 24bit 주소 공간에만 DMA 수행 가능 -일부 아키텍쳐에서는 가상적으로 접근할 수 있는 것보다 더 많은 양의 메모리를 물리적으로 접근할 수 있다. 따라서 일부 메모리는 커널 주소 공간에 상주할 수 없다. allocated as… Physical > Logical, 논리적주소로 물리적 주소를 매핑할 수 없다. DMA NORMAL HIGHMEM <linux/mmzone.h>에 정의 lock:구조체 스핀락 데이터 보호 O, 페이지 보호X watermark: 해당 구역 메모리 사용량 name: DMA, NORMAL, HighMem <mm/page_alloc.c>
7
Zone 구역 내용 물리적 메모리 ZONE_DMA DMA 가능 페이지 < 16MB ZONE_DMA32
32비트 장치들만 접근 가능 ZONE_NORMAL 일반적으로 접근 가능한 페이지 16-896MB ZONE_HIGHMEM 커널 주소 공간에 상주하지 않는 페이지;동적으로 연결되는 페이지, 상위 메모리 <896MB X86-64 와의 차이점 <linux/mmzone.h> 에 정의 ZONE_MOVABLE ZONE_PADDING Logical
8
DMA 구역 확보를 위해 ZONE_NORMAL 사용
Normal page DMA 구역 확보를 위해 ZONE_NORMAL 사용
9
Interface 페이지 할당 <linux/gfp.h>
struct page * alloc_pages(gfp_t gfp_mask, unsigned int order) 1<<order 만큼 연속된 물리적 페이지를 할당 첫번째 페이지의 page 구조체 포인터 반환 오류: NULL 반환 void * page_address(struct page *page) 물리적 페이지의 논리적 주소 포인터 반환 Unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) alloc_pages의 동작 첫 번째 페이지의 논리적 주소 반환 Unsigned long get_zeroed_page(unsigned int gfp_mask) __get_free_page()함수와 동일 할당된 페이지 내용을 0으로 채움 의도하지 않은 데이터가 있을 수 있음 order = 0 1페이지 struct page * alloc_page(gfp_t gfp_mask) Unsigned long __get_free_page(gfp_t gfp_mask)
10
Interface 페이지 반환 void __free_pages(struct page *page, unsigned int order) void free_pages(unsigned long addr, unsigned int order) void free_page(unsigned int addr) 할당받은 페이지만 반환 잘못사용하면 메모리 파괴됨 Ex) unsigned long page = __get_free_paes(GFP_KERNEL, 3); if(!page){ /*메모리 부족*/ return –ENOMEM; } free_pages(page, 3);
11
kmalloc() <linux/slab.h>
void * kmalloc(size_t size, gfp_t flags) 최소 size 바이트 길이를 가진 메모리 영역의 포인터 반환;물/논리적으로 연속 오류: NULL 반환 void kfree(const void *ptr) kmalloc() 을 통한 메모리 해제 Ex) char *buf buf = kmalloc(BUF_SIZE, GFP_KERNEL); if(!buf) /*오류 처리*/ kfree(buf);
12
vmalloc() <linux/vmalloc.h>선언, mm/ vmalloc.c 구현
void * vmalloc(unsigned long size) 최소 size 바이트 길이를 가진 메모리 영역의 포인터 반환;논리적으로 연속 오류: NULL 반환 *페이지 테이블의 정보를 수정해서 논리적 주소를 연속적으로 만듦 *페이지 단위로 페이지 테이블에 등록 TLB를 더 사용 kmalloc에 비해 *성능 저하 void vfree(const void *addr) vmalloc() 을 통한 메모리 해제 Ex) char *buf buf = vmalloc(16 * PAGE_SIZE); /*get 16 pages*/ if(!buf) /*오류 처리*/ vfree(buf);
13
Free list Normal Free list free free Add deallocation free list
Using object cache
14
Free list Normal Free list new new p = malloc() free list
initialization
15
Free list problem Kernel Which one? free list Slab layer
Memory lack Slab layer Kernel Can not control Which one? free list
16
Slab layer 자주 사용하는 자료구조는 캐시 *단편화 유발 방지 free list is sequential
객체, 페이지, 전체 캐시 등의 정보를 알고 있으면 정교한 처리 가능 일부 캐시가 프로세서 단위로 되어 있다면 SMP 락 없이 할당, 해제 가능 NUMA를 지원 하는 경우 메모리를 요청한 노드에 있는 메모리 할당 가능 여러 객체가 같은 캐시에 섞이지 않게, 저장되는 객체에 표시 할 수 있어야 함 *가용 메모리에서 충분한 연속된 메모리 공간을 찾을 수 없는 상황 SMP waiting 작업을 위한 데이터가 메모리의 어느 위치에 있는지 상관없이 작업할 수 있도록 프로세서에게 허용.
17
Slab layer Object Slab Object Object Cache Object Slab Object
18
Slab layer 객체 요청 부분사용 미사용 모두사용: 해제된 객체가 없음 부분사용: 할당, 해제된 객체
mm/slab.c kmem_list3 미사용 slabs_full 모두사용: 해제된 객체가 없음 slabs_patritial kmem_getpages() 부분사용: 할당, 해제된 객체 slabs_empty 미사용: 할당된 객체가 없음 새로운 Slab
19
Slab layer Struct slab{ struct list_headlist; unsigned long colouroff;
void *s_mem; unsigned int inuse; kmem_bufctl_t free; }; static inline void * kmem_getpages(struct kmem_cache *cachep, gfp_t flags){ void *addr; flags |= cachep->gfpflags; adr = (void*) __get_free_pages(flags, cachep->gfporder); return addr; }
20
Slab layer Struct kmem_cache * kmem_cache_create(const char *name,
size_t size, size_t align, unsigned long flags, void (*ctor) (void*)); 휴면 상태로 전환 될 수 있기 때문에 인터럽트 컨텍스트에서는 호출하면안됨 해제: int kmem_cache_destroy(struct kmem_cache *cachep) 모든 슬랩이 비어 있어야 함 호출하는 동안 캐시에 접근하면 안됨 name: 캐시 이름 size: 캐시에 들어갈 항목의 크기 align,: 슬랩 내부의 첫 번째 객체의 오프셋 default 0 flags: 캐시 동작 제어 default 0 ctor: 캐시 생성자 FLAGS 내용 SLAB_HWCACHE_ALIGN 캐시 라인에 맞춰 정렬, 잘못된 공유 현상 방지, 메모리 사용량 증가, 성능우선 SLAB_POISON a5a5a5a5 로 슬랩을 채움 (poisoning) 초기화 하지 않은 메모리 탐지 SLAB_RED_ZONE 버퍼 경계 넘침 현상 감지, 할당된 메모리 양측에 red zone 을 끼워 넣음 SLAB_PANIC 오류 시 panic 발생, VMA 할당 처럼 할당 작업이 절대로 실패해서는 안 될 때 사용 SLAB_CACHE_DMA DMA 처리 가능한 메모리에 슬랩을 할당, ZONE_DMA에 있어야 하는 경우 필요
21
Slab layer void * kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) 캐시에 들어있는 객체의 포인터 반환 내부 슬랩에 해제된 객체가 없으면 kmem_getpages() 호출 flags 인자가 __get_free_pages() 함수로 전달 void kmem_cache_free(struct kmem_cache *cachep, void *objp) 객체 해제 후 슬랩에 반환 cachep에 있는 objp 에 해제 표시
22
Stack – 단일 페이지 커널 스택 프로세스별 메모리 사용량 최소 단편화: 메모리 할당 작업이 어려워짐
인터럽트 핸들러: 프로세스의 커널 스택 사용 커널 스택 사용량 증가 Interrupt Stack 한 페이지 인터럽트 핸들러가 사용하는 각 프로세서 별로 존재 중단된 프로세스의 커널 스택 공유 안함자체스택
23
상위 메모리 연결 고정연결 임시연결 <linux/highmem.h>
상위 메모리에 있는 페이지는 고정된 커널 주소 공간 값이 없을 수 있다; 논리적 주소가 없을 수 있다 고정연결 임시연결 <linux/highmem.h> void *kmap(struct page *page) 휴면상태로 전환 될 수 있음 페이지 위치가 하위메모리: 페이지의 가상 주소 반환 상위메모리: 고정 연결 주소 반환 void kunmap(struct page *page) 고정연결 개수 제한 연결 해제 temporary, atomic mapping 컨텍스트가 휴면이 불가능한 상황일 때 void *kmap_atomic(struct page *page, enum km_type type) type: 연결의 목적 <asm-generic/kmap_types.h>에 정의 메모리 연결은 프로세서별로 고유 커널 선점 비활성 void kunmap_atomic(void *kvaddr, 연결 해제, 잊어버리기만 함(덮어 씌워짐)
24
unsigned long my_percpu[NR_CPUS];
int cpu; cpu = get_cpu(); my_percpu[cpu]++; printk(“my_percpu on cpu=%d is %lu\n”, cpu, my_percpu[cpu]); put_cpu(); Index data 1 2 … unsigned long my_percpu[NR_CPUS]; SMP
25
A프로세서가 B프로세서 캐시조작 A프로세서는 캐시를 비우거나 갱신
CPU별 할당 WHY -Lock이 필요 없을 수 있음 -Lock보다 비용이 적은 커널 선점 비활성화를 사용 -Cache invalidation 를 줄여줌 캐시 동기화 상태 유지 cache invalidation thrashing the cache 성능저하 A프로세서가 B프로세서 캐시조작 A프로세서는 캐시를 비우거나 갱신
26
New percpu interface 컴파일 시점의 CPU별 데이터 실행 시점의 CPU별 데이터
2.6 Kernel 이전 커널에서는 호환이 안됨 컴파일 시점의 CPU별 데이터 실행 시점의 CPU별 데이터 DEFINE_PER_CPU(type, name); 프로세스 별로 type name변수 생성 DECLARE_PER_CPU(type, name); 위 변수를 다른 곳에서 사용 하는 경우 get_cpu_var(name)++; 현재 프로세서의 name값 증가 put_cpu_var(name)++; 커널 선점 활성화 per_cpu(name, cpu)++; 지정한 프로세서의 name값 증가 선점 비활성화, Locking 없음 현재 프로세서 조작만 원자적 실행 보장 <linux/percpu.h> void *alloc_percpu(type); //매크로 void *__alloc_percpu(size_t size, size_t align); void free_percpu(const void*); get_cpu_var(ptr); 현재 프로세서의 해당 데이터를 가리키는 void 포인터 반환 put_cpu_var(ptr); 작업 마치고 커널 선점 활성화 void *percpu_ptr; unsigned long *foo; percpu_ptr = alloc_percpu(unsigned long); if(!ptr) //오류 처리 foo = get_cpu_var(percpu_ptr); put_cpu_var(percpu_ptr);
27
Summrary 메모리 할당: 일반적으로 kmalloc() 함수 이용
(1)GFP_ATOMIC, (2)GFP_KERNEL 플래그 이용 Case (1): 휴면상태 전환X, 우선순위가 높은 할당 작업 진행 Case (2): 휴면 상태 전환O like process context code without spinlock 상위메모리할당: alloc_pages() 함수 이용 가상적으로 연결필요: vmalloc() 함수 이용, 성능은 kmalloc()보다 낮음 큰 자료구조 생성 및 해제: 슬랩 캐시 사용 고려, freelist 제공
Similar presentations