- 메모리 관리 기법과 가상 메모리
물리 메모리의 한계를 극복하기 위해 가상메모리가 도입되었습니다.
프로그램들은 32bit 환경에서 232만큼, 즉 4GB 의 메모리 공간을 이용할 수 있게 되었습니다.
이는 물리적 4GB가 아닌 개념적인 공간으로 실제 동작에서는 필요한 만큼의
물리메모리를 제공합니다.
이렇게 가상메모리를 도입하므로 개념적으로 프로그램은 메모리 공간을 물리 메모리의 크기와는 상관없이 큰 공간을 이용할 수 있게 되었고, 실제 물리 메모리에선 필요한 만큼의 메모리 공간만 제공하므로 가능한 많은 태스크를 동시에 수행할 수 있게 되었습니다.
- 물리 메모리 관리 자료 구조
전체 물리 메모리의 정보를 표현하는 적절한 자료구조가 필요합니다.
2-1. NODE
리눅스에서 접근 속도가 같은 메모리의 집합을 뱅크(bank)라고 합니다. 이 뱅크를 표현하는 자료구조가 노드(node)입니다. 리눅스에선 하드웨어 시스템과는 관계없이 노드라는 자료구조로 전체 물리 메모리에 접근할 수 있습니다.
여러 개의 CPU가 있는 경우 NUMA(Non Uniform Memory Access)의 경우 여러 개의 노드가 있을 수 있고, UMA(Uniform Memory Access)의 경우엔 하나의 노드가 있습니다.
★리눅스에선 물리 메모리 할당 요청을 받을 경우 되도록 할당을 요청한 디스크가 수행되고 있는 CPU와 가까운 노드에서 메모리를 할당합니다.
하나의 노드는 구체적으로 pg_data_t라는 구조체로 표현됩니다.
2-2. ZONE
일부 ISA 버스 기반 디바이스의 정상동작을 위해선 16MB 이하 부분에 대한 특별한 할당이 필요합니다. 이 부분을 처리하기 위해 ZONE이 도입되었습니다. ZONE은 세 부분으로 나뉘어 집니다.
x86, 32bit 환경에서 물리 메모리의
0~16MB | ZONE_DMA |
16~896MB | ZONE_NORMAL |
896~end MB | ZONE_HIGHMEM |
리눅스 2.6.30에선 ZONE 구조체 안에 있던 pages_min, pages_low, pages_high가 3.10 소스에선 #define으로 구조체 안에서 빠져 나간 것을 확인할 수 있었습니다.
2-3. PAGE
각각의 ZONE은 자신에 속해 있는 물리 메모리들을 페이지 프레임으로 관리합니다. 모든 페이지 프레임당 하나의 page 구조체가 할당되어 이를 관리합니다. 결국 여러 개의 page가 모여 zone을 구성합니다. 이 zone들이 모여 node를 구성합니다.
- Buddy와 Slab
리눅스에서 전체 물리 메모리는 page, zone, node로 관리할 수 있습니다.
그렇다면 메모리 할당은 어떻게 일어날까요?
리눅스에서 메모리 할당의 최소 단위는 4KB입니다.
- 30 Byte, 60 Byte처럼 작은 크기는 Slab 할당자가 담당해 내부단편화를 줄입니다.
- 4KB보다 큰 공간, 예를 들어 10KB를 할당할 때는 12KB가 아닌 16KB를 버디 할당자가 할당해 외부 단편화를 줄입니다.
3-1 Buddy 할당자
ZONE 구조체에는 free_area라는 구조체 배열 필드가 있습니다. 이 배열의 인덱스는 페이지 프레임의 할당 수를 의미합니다. 예를 들어 인덱스 0의 페이지 프레임 할당 수는 20을 의미하여 1개의 페이지, 1번 인덱스의 경우 21을 의미해 2개의 페이지를 말합니다.
free_area 구조체의 free_list변수는 자신에게 할당된 free page frame을 list로 관리합니다.
자신이 관리하는 수준에서 페이지의 상태를 map 변수를 통해 비트맵으로 관리합니다.
3-2 Slab 할당자
예를 들어 64 Byte를 할당 받을 때 4KB페이지를 미리 64*64로 나누어 이 공간을 Buddy할당자가 아닌 Slab할당자로부터 할당한다.
Slab의 경우 Buddy로부터 할당 받은 페이지프레임을 Cache 단위로 쪼개고 이 Cache를 다시 Slab단위로 쪼개고 Slab을 다시 object 단위로 쪼개어 결국 이 Object를 할당한다.
free slab | 슬랩의 모든 객체(object)가 사용 가능 |
full slab | 슬랩의 모든 객체(object)가 사용 중 |
partial slab | 슬랩의 일부만 사용 가능 |
cache의 효율적 관리를 위해 kmem_cache_t 자료구조를 이용해 각각의 cache가 담고 있는 객체의 크기는 얼마인지 등의 정보를 표현합니다.
cache를 할당하는 함수를 살펴보면
kmem_cache_alloc() : 객체 할당
kmem_cache_free() : 객체 해제
에 관여합니다. 각각은 어느 cache에서 공간을 할당 받고, 어느 cache로 공간을 해제시켜야 하는지를 지정해줍니다. 만약 할당해줄 공간이 더 이상 없다면 Buddy로부터 프레임을 할당 받습니다.
출처 : 리눅스 커널 내부구조 - 백승재, 최종무 공저
'리눅스 커널 Linux kernel' 카테고리의 다른 글
5장 파일 시스템과 가상 파일 시스템 - 1 (0) | 2013.07.25 |
---|---|
4장 메모리관리 - 2 (0) | 2013.07.24 |
3장 태스크 관리 - 1 (0) | 2013.07.18 |
2장 리눅스 커널 구조 (0) | 2013.07.17 |
1장 리눅스의 소개 (0) | 2013.07.16 |