리눅스 커널의 이해 중에서 6장. 메모리 관리 김영재 데이터베이스 실험실
목차 Part I : 페이지 프레임 관리 Part II : 메모리 영역 관리 Part III : 불연속적인 메모리 영역 관리 Part IV : Q & A
Part I : 페이지 프레임 관리
페이지 프레임 관리 디스크립터 페이지 프레임에 대한 상태 정보를 배열에 저장 구조체 형식의 구조로 표현 페이지 프레임 구별 동적 메모리에 있는 페이지 프레임의 사용 유무 구조체 형식의 구조로 표현 count : 페이지 프레임의 사용 유무 판단 prev, next : 디스크립터의 이중 연결 리스트에 넣을 때 사용 flags : 페이지 프레임의 상태 기술
페이지 프레임 관리 페이지 프레임 상태를 기술하는 플래그 플래그명 의 미 PG_decr_after PG_dirty 의 미 PG_decr_after PG_dirty PG_error PG_free_after PG_DMA PG_locked PG_referenced PG_reserved PG_skip PG_slab PG_swap_chache PG_swap_unlock_after PG_uptodate 16장 참조 사용하지 않음 페이지 전송 중에 입출력 에러 발생 15장 참조 ISA DMA에서 사용 페이지 스왑 아웃 할 수 없음 해시 테이블을 통한 페이지 프레임 접근 커널 코드용으로 예약 혹은 사용할 수 없는 페이지 프레임 주소 공간의 일부분은 건너뛰기 위해 사용 슬랩에 존재 스왑 캐시에 존재 디스크 입출력 에러 발생없이 일기 작업을 마침
페이지 프레임 관리 메모리 배치 [그림 6-1] 메모리 배치 i386_endbase start_mem 0x1000 동적 메모리 i386_endbase start_mem 0x1000 동적 메모리 end_mem 예약된(하드웨어) 예약된(커널) [그림 6-1] 메모리 배치
페이지 프레임 관리 페이지 프레임 요구와 해제 페이지 프레임 요구 __get_free_pages(gft_mask, order) __get_dma_pages(gft_mask, order) DMA용으로 페이지 프레임을 얻을 경우 __get_free_page(gft_mask) 페이지 프레임 하나를 얻을 때 사용 get_free_page(gft_mask) 다음을 호출한 후 할당받은 페이지 프레임
페이지 프레임을 요구할 때 사용하는 플래그 값의 그룹 페이지 프레임 관리 gft_mask 플래그 __GFP_WAIT : 커널의 요청에 앞서 메모리를 해제 __GFP_IO : 커널이 해당 페이지 프레임에 기록하는 경우 __GFP_DMA : ISA DMA용으로 적합한 페이지 프레임 요구 __GFP_HIGH, __GFP_MED, __GFP_LOW : 요구의 우선순의 지정 그룹 이름 __GFP_WAIT __GFP_IO 우선 순위 GFP_ATOMIC GFP_BUFFER GFP_KERNEL GFP_NFS GFP_USER 1 __GFP_HIGH __GFP_LOW __GFP_MED 페이지 프레임을 요구할 때 사용하는 플래그 값의 그룹
페이지 프레임 관리 페이지 프레임 해제 free_pages(addr, order) __free_page(p) 디스크립터의 count 감소 __free_page(p) p가 가리키는 해당 디스크립터만 해제 Free_page(addr) 물리 주소 addr을 포함한 페이지 프레임 해제
페이지 프레임 관리 버디 시스템 알고리즘 외부 단편화 외부 단편화를 해결하기 위해 버디 시스템 체택 다른 크기의 연속적인 페이지 프레임 그룹의 빈번한 할당을 해제하여, 할당된 페이지 프레임 블록 사이에 빈 페이지 프레임이 흩어지는 현상 후에 큰 크기의 연속된 페이지 프레임을 할당하려고 할 때 충분한 빈 페이지가 존재하여도 메모리 할당 불가 외부 단편화를 해결하기 위해 버디 시스템 체택
[그림 6-2] 버디 시스템에서 사용하는 자료 구조 페이지 프레임 관리 자료 구조 20 21 22 23 24 25 26 27 28 29 bitmaps free_area[0] mem-map [그림 6-2] 버디 시스템에서 사용하는 자료 구조
__get_free_pages() 종료 페이지 프레임 관리 블록 할당 __get_free_pages() nr_free_page> freepages.min 거짓 참 REQUEUE_TYPE 페이지 프레임 회수 free_area 인덱스인 freepages.min 1 __get_free_pages() 종료
페이지 프레임 관리 블록 해제 free_page_ok() 함수를 사용 free_page_ok()의 매개변수 map_nr : 해제할 블록에 들어 있는 페이지 프레임 번호 order : 블록 크기에 로그를 취한 값 type : DMA용 페이지 프레임인지 확인 지역변수 선언 초기화 map_nrd의 비트 전환 mask, area, index, map_nr 변수 갱신 while (mask+(1<<9)) 버디 블록이 비어 있음 버디 블록이 비어 있지 않음 올바른 리스트 추가
Part II : 메모리 영역 관리
메모리 영역 관리 내부 단편화 요청한 메모리의 크기와 이 요청을 처리하기 위해 할당하는 메모리 영역의 크기가 일치하지 않을 경우 발생 기하학적으로 분보된 크기에 따른 메모리 영역 제공 32바이트부터 131056바이트 크기의 기하학적으로 분포된 빈 메모리 리스트 13개 생성 페이지 프레임 해제 시 버디 시스템 사용
메모리 영역 관리 슬랩 할당자 슬랩 캐시 [그림 6-3] 슬랩 할당자의 구성 요소
메모리 영역 관리 캐시 디스크립터 struct kmen_chache_s 자료형 테이블 c_name : 캐시 이름에 대한 포인터 c_firstp, c_lastp : 각 캐시에 있는 슬랩 디스크립터를 가리킴 c_freep : 빈 객체를 갖는 첫째 슬랩 디스크립터의 s_nextp 필드를 가리킴 c_num : 슬랩 하나에 들어 있는 객체 수 c_offset : 캐시에 들어있는 객체 크기 c_gfporder : 연속된 페이지 프레임 수의 로그를 취한 값 c_ctor, c_dtor : 생성자와 소멸자 메소드를 가리킴 c_nextp : 다음 캐시 디스크립터를 가리킴 c_flags : 몇 가지 영구적인 속성을 나타내는 플래그 배열 c_magic : 선택한 매직 넘버
메모리 영역 관리 슬랩 디스크립터 struct kmen_slab_s 자료형과 유사 s_inuse : 슬랩에서 현재 할당된 객체 수 s_mem : 슬랩에 있는 첫째 객체 s_freep : 슬랩에 있는 첫째 빈 객체 s_nextp, s_prevp : 슬랩 디스크립터의 다음 필드와 이전 필드를 가리킴 s_dma : DMA 프로세서가 사용할 수 있는 객체 s_magic : c_magic 필드와 비슷
[그림 6-4] 캐시 디스크립터와 슬랩 디스크립터 사이의 관계 메모리 영역 관리 캐시 디스크립터 캐시 디스크립터 캐시 디스크립터 슬랩 디스크립터 슬랩 디스크립터 슬랩 디스크립터 슬랩 디스크립터 슬랩 디스크립터 슬랩 디스크립터 슬랩 디스크립터 s_nextp 모두 사용 중인 슬랩 슬랩 디스크립터 s_prevp c_nextp 일부만 사용 중인 슬랩 c_freep 비어 있는 슬랩 c_fristp c_lastp [그림 6-4] 캐시 디스크립터와 슬랩 디스크립터 사이의 관계
메모리 영역 관리 일반 캐시와 특수 캐시 일반 캐시 특수 캐시 슬랩 할당자에서 필요로 할 때 사용 첫째 캐시에 커널 사용하고 나머지에 캐시 디스크립터 사용 둘째 캐시에 슬랩 내부에 저장되지 않은 슬랩 디스크립터 저장 추가 캐시는 기하학적으로 분포된 메모리 영역에 할당 kmen_cache_init()과 kmen_cache_sizes_init() 함수로 생성 특수 캐시 커널의 나머지 부분에서 사용 kmen_eache_create() 함수로 생성
메모리 영역 관리 버디 시스템의 슬랩 할당자 인터페이스 버디 시스템 알고리즘을 사용하여 빈 페이지 프레임 할당 kmem_getpages() 함수 호출 cachep : 캐시의 캐시 디스크립터를 가리킴 flags : 페이지 프레임을 할당하는 방법 지정 dma : ISA DMA에 적합한지 설정
kmem_slab_link _end() 메모리 영역 관리 캐시에 슬랩 할당 캐시에 슬랩에 할당하는 경우 새 객체를 할당해 달라는 요청이 왔을 때 캐시에 빈 객체가 없을 때 캐시에 슬림 할당 슬랩 디스크립터를 캐시 슬랩 리스트 끝에 추가 슬랩할당자 kmem_slab_link _end() kmen_cache_ grow() 버디 시스템에 프레임 그룹 할당 kmem_cache _init_objs() kmem_getpages() kmem_cache _slabmgnt() 생성자 메소드 정의 슬랩 할당자를 새로 받음
메모리 영역 관리 캐시에서 슬랩 제거 슬랩을 해제할 경우 버디 시스템이 새로 페이지 프레임 그룹을 할당해 달라는 요구를 처리할 수 없을 때 슬랩에 비어있을 때 페이지 프레임 검색 커 널 kmem_slab _destroy() try_to_free _page() 슬랩을 제거 빈 슬랩을 가진 캐시 선택 kmem_slab _unlink() kmem_cache _reap() 슬랩 제거
[그림 6-5]슬랩 디스크립터와 객체 디스크립터 사이의 관계 메모리 영역 관리 객체 디스크립터 내부에 객체 디스크립터를 포함한 슬랩 s_mem s_freep 할당된 객체 빈 객체 할당된 객체 빈 객체 슬랩 디스크립터 외부에 객체 디스크립터를 포함한 슬랩 s_mem s_freep 할당된 객체 빈 객체 할당된 객체 빈 객체 슬랩 디스크립터 s_index [그림 6-5]슬랩 디스크립터와 객체 디스크립터 사이의 관계
메모리 영역 관리 메모리에서 객체 정렬 메모리에서 슬랩 할당자가 관리하는 객체 정렬 정렬 계수의 배수가 되는 메모리 셀에 객체 저장 최대 정렬 계수는 4096(페이지 프레임 크기) kmem_cache_create() 함수 객체 크기가 캐시 라인의 절반보다 크면, 램을 캐시 라인에 있도록 정렬 객체 크기를 L1_CACHE_BYTES 계수에 따라 올림
메모리 영역 관리 슬랩 컬러링 유쾌하지 않은 캐시 동작 [그림 6-6] 컬러 col과 정렬aln 슬랩 객 체 객 체 객 체 디스크립터 col*ain osize osize osize osize free_col * aln dsize num * osize [그림 6-6] 컬러 col과 정렬aln 슬랩
메모리 영역 관리 캐시에 객체 할당 slabp->s_index =0 거짓 kmem_cache_alloc() 캐시에 새로운 슬랩 추가 캐시 디스크립터 유무 참 c_freep 필드의 빈 객체의 첫 슬랩 s_nextp 필드 주소 가져옴 객체 디스크립터 슬랩 내부의 객체 다음에 저장 객체 디스크립터 슬랩의 외부 메모리 영역을 지정 slabp가 슬랩을 가리키는가? 아니오 Alloc_new_slab로 점프 예 bufp 슬랩이 있는 첫 빈 객체의 주소 설정
메모리 영역 관리 캐시에 객체 해제 kmem_cache_free() kmem_cache_one_free() cachep와 objp 검사 bufp->buf_nexp=Null 디스크립터와 객체 디스크립터의 주소 빈 객체 리스트 해제되는 객체 삽입 cachep->c_flags 플래그 디스크립터의 위치 파악 slabp->s_magic 필드와 slabp->s_inuse>0 검사 kmem_cache_full_free() 슬랩 디스크립터를 새 위치로 이동 slabp->s_inuse 감소 빈 객체를 슬랩 리스트 추가
Part III : 불연속적인 메모리 영역 관리
불연속적인 메모리 영역 관리 메모리 영역에 대한 요청이 드물 경우, 연속적인 선형 주소를 통해 접근 장 점: 외부단편화 문제를 피함 단 점: 커널 페이지 테이블을 다뤄야 함 불연속적인 메모리 영역 사용의 예 활성화된 스왑 영역용으로 자료 구조를 할당 모듈용 또는 몇몇 입출력 드라이버용으로 버퍼를 할당
불연속적인 메모리 영역 관리 불연속적인 메모리 영역의 선형 주소 선형주소 부호가 없는 32비트 크기의 정수값 4GB까지 주소를 지정하는 데 사용 메모리 영역에 대한 요청이 드물 경우, 연속적 선형 주소 공간은 두 부분으로 나뉨 0x00000000~PAGE_OFFSET-1 : 사용자모드, 커널모드 모두 접근가능 PAGE_OFFSET~0xffffffff : 커널 모드 4GB의 선형주소 중 1GB영역이 커널용으로 예약 예약된 영역 다음의 선형주소를 이용하여 불연속적인 메모리 영역을 매핑하는 데 사용
[그림 6-7] PAGE_OFFSET부터 시작하는 선형 주소 구간 불연속적인 메모리 영역 관리 high_memory PAGE_OFFSFT VMALLOC_START 물리 메모리 영 역 영 역 영 역 8MB 4KB 4KB [그림 6-7] PAGE_OFFSET부터 시작하는 선형 주소 구간
불연속적인 메모리 영역 관리 불연속적인 메모리 영역 디스크립터 불연속적인 메모리 영역마다 struct vm_struct 자료형 디스크립터와 연결 Next필드를 이용하여 간단한 리스트에 들어감
불연속적인 메모리 영역 관리 불연속적인 메모리 영역 할당 vmalloc()함수 사용 요청한 메모리를 할당할 수 있으면 새 영역의 시작 선형 주소를 반환 요청한 메모리를 할당할 수 없으면 NULL포인터를 반환
불연속적인 메모리 영역 관리 불연속적인 메모리 영역 해제 Vfree()함수 사용 매개변수 는 해제할 영역의 시작 선형 주소로 들어감 리스트를 검색하여 해제할 영역과 관련된 영역 디스크립터 주소를 찾음 불연속적인 메모리 영역에 할당한 각 페이지 프레임을 버디 시스템의 free_page()함수를 이용하여 해제
Part VI : Q & A