자료구조를 할당하고 해제하는 것은 커널 내부에서 이뤄지는 흔한 작업들 중 하나이다.
빈번한 데이터의 할당과 해제를 손쉽게 하기 위해, 프로그래머는 종종 가용 리스트(풀)를 사용한다.
가용리스트는 이미 할당되어서, 사용 가능한 자료구조의 블록을 담고 있다. 즉, 커널에서 이 리스트의 노드를 가져와서 사용하고시 반납하는 식으로 사용하게된다. 가용리스트는 자주 사용되는 객체를 캐시하게 된다.
커널에서 가용 리스트를 사용할 떄의 주요 문제점 중 하나는 전역적인 조절 방법이 없다는 것이다.
즉, 커널에서 사용할 수 있는 메모리가 부족한경우, 모든 가용리스트에 이 사실을 통보하여 각 가용리스트가 사용하는 캐시의 크기를 줄일 수 있는 방법이 없다는 것이다. 커널은 임의의 가용 리스트에 대해 전혀 알지 못한다. 이러한 문제를 해결하기 위해 슬랩 레이어(slab layer, 슬랩 할당자)를 제공한다. 슬랩 레이어는 마치 범용 자료구조 캐시와 같은 역할을 한다.
슬랩 레이어에는 다음과 같은 규칙이 있다.
- 자주 사용되는 자료 구조는 빈번하게 할당/해제되므로 캐시한다.
- 빈번한 할당과 해제가 발생하면 메모리가 단편화가 될 수 있다. 이를 방지하기 위해 가용 리스트를 연속적으로 배치한다. 해제된 자료 구조는 다시 가용 리스트로 반환되므로 단편화는 일어나지 않는다.
- 가용 리스트느 반납된 객체를 재사용할 수 있으므로 빈번한 할당과 해제 동안의 성능을 향상시킨다.
- 만약 할당자가 객체의 크기, 페이지 크기, 전체 캐시 크기 등의 정보를 알고 있다면 더 적절한 판단을 내릴 수 있다.
- 캐시가 각 프로세서별로 존재하는 경우 SMP 락 없이도 할당과 해제를 할 수 있다.
- 가용 리스트에 저장된 객체를 굽누함으로써, 여러 객체가 동일한 캐시 라인에 매핑되는 것을 말을 수 있다.
슬랩 레이어의 구조
슬랩 레이어는 객체를 캐시라는 그룹으로 나누고, 각 그룹에 서로 다른 유형의 객체를 저장한다. 즉 객체 유형마다 하나의 캐시가 존재한다. 예를 들면, 프로세스 설명자(task_struct 리스트)에 대해 캐시가 하나 할당되고, inode객체(struct inode)에는 다른 캐시가 할당되는 식이다. 흥미롭게도, kmalloc() 인터페이스는 일련의 범용 캐시를 사용하여 슬랩 레이어 위에서 구현되어 있따
캐시는 여러 개의 슬랩으로 나뉘며, 각 슬랩은 하나 이상의 물리적으로 연속된 페이지로 구성된다. 대개의 경우 슬랩은 단 하나의 페이지로, 캐시는 여러 슬랩으로 구성된다.
각 슬랩은 객체를 포함하는데, 이 객체는 바로 캐시되는 자료 구조이다. 각 슬랩은 full, partial, empty의 세가지 중 한가지 상태에 있다. full 슬랩에는 사용할 수 있는 객체가 없다(슬랩에 있는 모드느 객체가 할당됨). 반면, empty 슬랩에는 할당된 객체가 없다(슬랩의 모든 객체가 사용가능). partial 슬랩이 있다면 여기에서 요청을 처리하며, 그렇지 않으면 empty 슬랩에서 처리한다. 또 만약 empty 슬랩이 없는 경우 새로 하나를 생성한다. 물론 full 슬랩에는 가용한 객체가 없으므로 이런 요청을 처리할 수 없다.
예를들어, inode구조체를 살펴보자. 이 구조체는 메모리 상에서 디스크 inode를 표현한 것이다. 이 구조체는 자주 생성 및 소멸되기 때문에 슬랩 할당자를 통해 관리하는 것이 좋다. 따라서 struct inode는 inode_cachep캐시에 할당된다.
이 캐시는 하나 이상의 슬랩으로 구성되며, 객체가 수가 많기 때문에 슬랩도 많을 것이다. 각 슬랩은 가능한 많은 struct inode구조체를 포함한다. 커널에서 새로운 inode 구조체를 요청하면, 커널은 이미할당되었지만, 아직 사용하지 않은 구조체의 포인터 partial 슬랩 또는 이런 슬랩이 없다면 empty 슬랩에서 찾아 리턴한다. 커널에서 inode객체의 사용을 끝내면 슬랩 할당자는 해당 객체를 가요한 상태로 표시한다.
내 정리
struct type : cache = 1 :1
cache : slab = 1 : M
slab : object = 1 : M
각 캐시는 keme_cache_s 구조체로 표현된다. 이 구조체는 세 개의 리스트 slabs_full, slabs_partial, slabs_empty를 담고 있으며, 이 리스트는 kmem_list3구조체로 표현된다. 이들 리스트는 캐시와 관련된 모든 슬랩을 포함한다. 슬랩 설명자인 struct slab 구조체는 각 슬랩 표현한다.
struct kmem_cache_s{
struct kmem_list3* l3;
}
struct kmem_list3{
struct slab slab_full;
struct slab slab_partial;
struct slab slab_empty;
}
struct slab{
빈번한 데이터의 할당과 해제를 손쉽게 하기 위해, 프로그래머는 종종 가용 리스트(풀)를 사용한다.
가용리스트는 이미 할당되어서, 사용 가능한 자료구조의 블록을 담고 있다. 즉, 커널에서 이 리스트의 노드를 가져와서 사용하고시 반납하는 식으로 사용하게된다. 가용리스트는 자주 사용되는 객체를 캐시하게 된다.
커널에서 가용 리스트를 사용할 떄의 주요 문제점 중 하나는 전역적인 조절 방법이 없다는 것이다.
즉, 커널에서 사용할 수 있는 메모리가 부족한경우, 모든 가용리스트에 이 사실을 통보하여 각 가용리스트가 사용하는 캐시의 크기를 줄일 수 있는 방법이 없다는 것이다. 커널은 임의의 가용 리스트에 대해 전혀 알지 못한다. 이러한 문제를 해결하기 위해 슬랩 레이어(slab layer, 슬랩 할당자)를 제공한다. 슬랩 레이어는 마치 범용 자료구조 캐시와 같은 역할을 한다.
슬랩 레이어에는 다음과 같은 규칙이 있다.
- 자주 사용되는 자료 구조는 빈번하게 할당/해제되므로 캐시한다.
- 빈번한 할당과 해제가 발생하면 메모리가 단편화가 될 수 있다. 이를 방지하기 위해 가용 리스트를 연속적으로 배치한다. 해제된 자료 구조는 다시 가용 리스트로 반환되므로 단편화는 일어나지 않는다.
- 가용 리스트느 반납된 객체를 재사용할 수 있으므로 빈번한 할당과 해제 동안의 성능을 향상시킨다.
- 만약 할당자가 객체의 크기, 페이지 크기, 전체 캐시 크기 등의 정보를 알고 있다면 더 적절한 판단을 내릴 수 있다.
- 캐시가 각 프로세서별로 존재하는 경우 SMP 락 없이도 할당과 해제를 할 수 있다.
- 가용 리스트에 저장된 객체를 굽누함으로써, 여러 객체가 동일한 캐시 라인에 매핑되는 것을 말을 수 있다.
슬랩 레이어의 구조
슬랩 레이어는 객체를 캐시라는 그룹으로 나누고, 각 그룹에 서로 다른 유형의 객체를 저장한다. 즉 객체 유형마다 하나의 캐시가 존재한다. 예를 들면, 프로세스 설명자(task_struct 리스트)에 대해 캐시가 하나 할당되고, inode객체(struct inode)에는 다른 캐시가 할당되는 식이다. 흥미롭게도, kmalloc() 인터페이스는 일련의 범용 캐시를 사용하여 슬랩 레이어 위에서 구현되어 있따
캐시는 여러 개의 슬랩으로 나뉘며, 각 슬랩은 하나 이상의 물리적으로 연속된 페이지로 구성된다. 대개의 경우 슬랩은 단 하나의 페이지로, 캐시는 여러 슬랩으로 구성된다.
각 슬랩은 객체를 포함하는데, 이 객체는 바로 캐시되는 자료 구조이다. 각 슬랩은 full, partial, empty의 세가지 중 한가지 상태에 있다. full 슬랩에는 사용할 수 있는 객체가 없다(슬랩에 있는 모드느 객체가 할당됨). 반면, empty 슬랩에는 할당된 객체가 없다(슬랩의 모든 객체가 사용가능). partial 슬랩이 있다면 여기에서 요청을 처리하며, 그렇지 않으면 empty 슬랩에서 처리한다. 또 만약 empty 슬랩이 없는 경우 새로 하나를 생성한다. 물론 full 슬랩에는 가용한 객체가 없으므로 이런 요청을 처리할 수 없다.
예를들어, inode구조체를 살펴보자. 이 구조체는 메모리 상에서 디스크 inode를 표현한 것이다. 이 구조체는 자주 생성 및 소멸되기 때문에 슬랩 할당자를 통해 관리하는 것이 좋다. 따라서 struct inode는 inode_cachep캐시에 할당된다.
이 캐시는 하나 이상의 슬랩으로 구성되며, 객체가 수가 많기 때문에 슬랩도 많을 것이다. 각 슬랩은 가능한 많은 struct inode구조체를 포함한다. 커널에서 새로운 inode 구조체를 요청하면, 커널은 이미할당되었지만, 아직 사용하지 않은 구조체의 포인터 partial 슬랩 또는 이런 슬랩이 없다면 empty 슬랩에서 찾아 리턴한다. 커널에서 inode객체의 사용을 끝내면 슬랩 할당자는 해당 객체를 가요한 상태로 표시한다.
내 정리
struct type : cache = 1 :1
cache : slab = 1 : M
slab : object = 1 : M
각 캐시는 keme_cache_s 구조체로 표현된다. 이 구조체는 세 개의 리스트 slabs_full, slabs_partial, slabs_empty를 담고 있으며, 이 리스트는 kmem_list3구조체로 표현된다. 이들 리스트는 캐시와 관련된 모든 슬랩을 포함한다. 슬랩 설명자인 struct slab 구조체는 각 슬랩 표현한다.
struct kmem_cache_s{
struct kmem_list3* l3;
}
struct kmem_list3{
struct slab slab_full;
struct slab slab_partial;
struct slab slab_empty;
}
273struct kmem_list3 { 274 struct list_head slabs_partial; /* partial list first, better asm code */ 275 struct list_head slabs_full; 276 struct list_head slabs_free; 277 unsigned long free_objects; 278 unsigned int free_limit; 279 unsigned int colour_next; /* Per-node cache coloring */ 280 spinlock_t list_lock; 281 struct array_cache *shared; /* shared per node */ 282 struct array_cache **alien; /* on other nodes */ 283 unsigned long next_reap; /* updated without locking */ 284 int free_touched; /* updated without locking */ 285};
struct slab{
struct list_head list; //full, partial, empty list
unsigned long coloroff; //슬랩 컬러링 위한 오프셋
void * s_mem; //슬랩 첫번째 객체
unsigned int inuse; //할당된 객체의 개수
kmem_bufctl_t free; //(존재할 경우) 첫번째 가용 객체
unsigned long coloroff; //슬랩 컬러링 위한 오프셋
void * s_mem; //슬랩 첫번째 객체
unsigned int inuse; //할당된 객체의 개수
kmem_bufctl_t free; //(존재할 경우) 첫번째 가용 객체
}
221struct slab { 222 union { 223 struct { 224 struct list_head list; 225 unsigned long colouroff; 226 void *s_mem; /* including colour offset */ 227 unsigned int inuse; /* num of objs active in slab */ 228 kmem_bufctl_t free; 229 unsigned short nodeid; 230 }; 231 struct slab_rcu __slab_cover_slab_rcu; 232 }; 233};
'OS이야기' 카테고리의 다른 글
슬랩 할당자 인터페이스 (0) | 2011.10.20 |
---|---|
kmem_pages(kmem_cache_t *cachep, int flags, int nodeid) (0) | 2011.10.20 |
vmalloc() (0) | 2011.10.19 |
kfree() (1) | 2011.10.19 |
kmalloc() (0) | 2011.10.19 |