Linux의 동적 메모리 관리 프로세스 ptmalloc2의 주요 객체와 Tcache의 구성요소 및 동작과정

 

 

 

개요

 

 

 

운영체제에서 한정된 메모리 자원을 각 프로세스에 효율적으로 배분하는 일은 필수적인데, 이러한 역할을 해주는 것을 Memory Allocator라고 한다.

 

 

Memory Allocator는 사용되는 알고리즘에 따라 여러 종류가 있는데, Linux에서는 GLibc로 구현된 ptmalloc2를 사용한다. ptmalloc2는 프로세스 메모리의 Heap 영역에서, 동적으로 할당되고 해제되는 메모리 영역을 관리하여 메모리 할당의 속도를 향상하며 메모리의 낭비를 막아준다.

 

 

참고로 GLibc(GNU C Library)는 리눅스에서 가장 많이 사용되는 Libc(표준 C 라이브러리)이며 scanf, printf, malloc, free 등 기본적으로 필요한 함수들을 제공한다. 일반적으로 우리가 C언어를 작성할 때 사용하는 #include<stdio.h>가 있다.

 

 

 

 

 

 

 


ptmalloc2의 주요 객체

 

 

 

ptmalloc2가 관리하는 주요 객체로는 Chunk, Bin, Arena, Tcache가 있다. 여기서는 64bit 환경을 기준으로 소개한다.

 

1) Chunk

청크(Chunk)는 ptmalloc2이 할당한 메모리 공간을 말하며, 헤더와 데이터로 구성된다. 또한 청크는 메모리 동적 할당 시 Heap 영역에 생성되며, 해제 시 저장소에 보관되어 이후 같은 크기의 청크를 다시 할당하고자 할 때 보관된 청크를 다시 사용한다.

 

사용중인 청크와 해제된 청크의 구조

 

헤더 구성 크기
(64bit 기준)
설명
prev_size 8byte 인접한 직전 청크의 크기, 청크 병합 시 직전 청크를 찾는데 사용 
size 8byte 현재 청크의 크기, 64bit 환경에서 하위 3bit는 청크 관리를 위한 flag로 사용
fd 8byte 연결 리스트에서 다음 청크의 주소
bk 8byte 연결 리스트에서 이전 청크의 주소

 

Heap 영역에 할당되어 사용중인 청크가 해제되면, 해제되는 청크의 헤더 부분에 fd와 bk 구성이 추가된다. 이는 연결 리스트(free list) 방식으로 관리되는 저장소에서 각각 다음 청크의 주소와 이전 청크의 주소를 가리키며 해제된 청크의 관리를 용이하게 한다.

 

 

 

 

2) Bin

Bin은 해제된 청크들을 보관하는 free list 구조체이며, 사용이 끝난 해제된 청크들이 보관된다. 청크의 크기에 따라 Fast bin, Small bin, Large bin, Unsorted bin으로 분류되며, 크게 두 개의 배열로 나뉘어 보관된다.

 

Arena의 Bin 구조

 

종류 개수 보관되는 청크의 크기
(64bit 기준)
병합 여부 보관 방식
Fast bin 10개
(7개만 사용)
32byte 이상
128byte 이하의 청크
X 단일 연결 리스트
(LIFO, Last In First Out)
Small bin 62개 32byte 이상
1,024byte 미만의 청크
O 원형 이중 연결 리스트
(FIFO, First In First Out)
Large bin 63개 1,024byte 이상의 청크 O
Unsorted bin 1개 Small bin / Large bin
(분류되지 않은 청크 보관)
-

 

Fast bin은 작은 크기의 청크들을 관리하며 속도 및 효율성을 향상하기 위해 인접한 청크가 있어도 병합 과정을 진행하지 않는다. 또한 Unsorted bin에는 분류되지 못한 청크들이 존재하며, 이후 탐색된 청크들이 크기에 맞게 Small bin 또는 Large bin으로 분류된다. 이렇게 분류된 Small binLarge bin은 인접한 청크가 있으면 병합 과정을 수행하여 메모리의 단편화를 방지한다.

 

 

 

 

3) Arena

Arena는 서로 다른 메모리 영역을 공유하며 사용할 수 있도록 도와주는 Heap 영역이다. 이는 멀티 스레드 환경에서 한 스레드가 공유 자원을 독점하는 것을 막기 위해 도입된 개념으로 fastbin, smallbin, largebin 등의 정보를 모두 담고 있다. 여기서 ptmalloc2는 멀티 스레드 환경에서 자원의 독점을 막기 위하여 최대 64개의 Arena를 생성할 수 있도록 한다.

 

 

 

 

 

 

 


Tcache란?

 

 

 

ptmalloc2에서 Arena는 최대 64개를 생성할 수 있다고 하였다. 그러나 64개만으로도 충분하지 못할 경우가 생기는데, 이를 해결하기 위하여 GLibc2.26부터 Tcache라는 기술이 도입되었다.

 

 

Tcache(Thread local Caching)란 각 스레드 내에서 해제된 청크를 보관하는 저장소를 말하며, 해제된 청크를 Arena가 아닌 스레드 내 독립적으로 보관하고 재사용하며 Heap 영역의 작업을 효율적으로 도와준다.

 

 

각 스레드 별로 최대 64개의 Tcache bin을 생성할 수 있으며, 하나의 Tcache bin에는 최대 7개의 청크를 보관할 수 있다. 7개가 모두 사용되면 그 이후의 해제된 청크는 Arena의 영역에서 관리하게 된다.

 

종류 개수 보관되는 청크의 크기
(64bit 기준)
병합 여부 보관 방식
Tcache bin 64개
(1개당 7개의 청크)
24byte 이상
1032byte 이하의 청크
X 단일 연결 리스트
(LIFO, Last In First Out)

 

 

 

또한, Tcache bin에 있는 청크들을 Arena의 bin에 있는 청크들과는 다른 헤더 구조를 가진다. Tcache bin은 next라는 포인터 변수를 사용하여 동일한 크기의 청크들을 연결하여 관리한다.

 

Tcache에서의 해제된 청크 구조

 

 

 

 

 

 

 


Tcache의 구성요소 및 동작과정

 

 

 

Tcache bin은 tcache_entry 및 tcache_perthread_struct 구조체로 보관되며, Tcache의 여러 함수를 통해 각 구조체를 생성하고 관리된다.

 

 

tcache_entry

각 Tcache bin은 tcache_entry라는 구조체로 관리되며, 최대 7개의 같은 크기를 갖는 청크들이 next 포인터를 통해 연결된다.

 

tcache_entry의 구조

 

 

tcache_perthread_struct

또한, 이러한 64개의 Tcache bin, 즉 64개의 tcache_entry를 tcache_perthread_struct라는 구조체를 통해 관리한다. 해당 구조체는 두 개의 배열을 가지는데, 서로 다른 크기의 청크들을 가지는 tcache_entry를 entries[ ] 배열에 차례대로 보관하며, counts[ ] 배열에 해당 엔트리가 가지는 청크의 개수를 기록한다.

 

tcache_perthread_struct의 구조

 

 

이러한 구조체는 Tcache에서 아래와 같은 주요 함수들을 통해 생성되며 관리된다.

 

  • tcache_init(void) : tcache_perthread_struct를 생성한다.
  • tcache_get(size_t tc_idx) : tcache list에 있는 청크의 연결을 끊고 반환값으로 청크의 주소를 반환한다.
  • tcache_put(mchunkptr chunk, size_t tc_idx) : tcache list에 해제된 청크를 넣고 이전 청크와 연결한다.

 

 

여기서 tcache_get( )의 경우, tcache_perthread_struct에서 배열의 인덱스를 가리키는 tc_idx의 값을 검사하여 음수가 되거나 배열의 범위를 벗어나게 되면 프로그램을 종료한다.

 

 

 

 

 

+ Recent posts