chunk structure
glibc는 메모리 동적 할당 api를 제공하기 위해 내부적으로 메모리를 chunk 단위로 관리한다
allocated chunk
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if unallocated (P clear) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |A|M|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
. .
. (malloc_usable_size() bytes) .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (size of chunk, but used for application data) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of next chunk, in bytes |A|0|1|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- prev_size : 이전 chunk가 free chunk이면 이 영역에는 이전 chunk의 크기가 저장된다. 반대로 할당된 chunk이면 해당 chunk의 user data가 저장된다
- mchunk_size : 현재 chunk의 크기. 마지막 세 개의 비트(P, A, M)는 flag bit들이다
- P (PREV_INUSE) : 이전 chunk가 할당되었는지 나타낸다. 특정 chunk가 할당되었는지 확인하려면 그 다음 chunk의 bit 0를 확인하면 된다
- M (IS_MMAPPED) : 현재 chunk가 system call에 의해 할당되었는지를 나타낸다
- A (NON_MAIN_ARENA) : main arena에 포함된 chunk이면 0, thread가 할당받은 arena에 포함된 chunk이면 1
free chunk
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if unallocated (P clear) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' | Size of chunk, in bytes |A|0|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (fd)Forward pointer to next chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (bk)Back pointer to previous chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unused space (may be 0 bytes long) .
. .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`foot:' | Size of chunk, in bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of next chunk, in bytes |A|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- free chunk에만 있는 필드
- fd(forward pointer) : 같은 bin에서 다음 chunk를 가리킨다
- bk(backward pointer) : 같은 bin에서 이전 chunk를 가리킨다
Arena
- 서로 다른 종류의 chunk들을 가리키는 포인터들이 저장된 구조체
- 각 thread는 메모리를 요청하면 하나의 arena를 할당받는다
- arena는 main arena와 thread arena 두 종류로 나뉜다
- main arena는 프로세스 당 한 개 존재한다
- 새로운 스레드가 메모리를 요청하면 global linked list에서 arena를 하나 할당해준다
- 새로운 arena가 없고 전체 arena의 개수가 M_ARENA_MAX를 넘지 않았다면 malloc은 arena를 하나 새로 생성한다
Heap
- heap은 하나의 frame header와 chunk들로 구성되어 있다
- Glibc는 OS로부터 메모리를 heap 단위로 요청하고 반환한다
- glibc에서 heap은 프로세스 메모리 공간 중 heap영역과는 다른 의미이다
- glibc에서 사용하는 논리적 단위이다
- glibc는 OS에게 메모리를 요청/반환할 때 heap이라는 큰 단위로 메모리를 요청하고 반환한다
- main arena와 heap arena는 생성될 때 heap을 하나 가진다
- thread arena의 heap 크기가 특정 값(64MB) 이상이 되면 새로운 heap이 추가된다
- heap들은 연결 리스트로 관리된다
- heap이 처음 생성되면 heap에는 top chunk라는 chunk 하나만 존재한다. 이 heap으로 메모리 요청이 올 때마다 top chunk에서 chunk 하나를 분리한다