Pintos에서 이는 중요한 개념이다
사실 당연히 중요하겠지만 아무튼
pintos에는 두 종류의 메모리 할당자가 존재한다
하나는 페이지 단위로
다른 하나는 임의의 크기로다
include/threads/palloc.h
에 페이지 할당자가 선언되어 있는데
얜 페이지(page) 단위로 메모리를 할당한다
보통 한 번에 한 페이지로 쓰지만 여러 페이지도 한 번에 가능하다
페이지 할당자는 자신이 관리하는 메모리를 두 개의 풀로 나눈다
커널 풀(kernel pool) 유저 풀(user pool)
기본적으로, 1MB를 초과하는 시스템 메모리를 두 풀이 반반씩 나눠 갖지만,
이 비율은 ul
커널 명령줄 옵션으로 변경가능하다
할당 요청은 둘 중 하나에서만 이뤄지고 말이다
유저 풀은 사용자 프로세스용 메모리
커널 풀은 그 외 모든 할당
각 풀의 사용 현황은 비트맵(bitmap) 으로 추적한다
0이면 비어있고 1이면 차있다는 거 말이다
이것도 메모리 할당이라 단편화가 발생한다
이를 피하고자 연속 할당 요청은 자제 하란다
페이지 할당자의 타입과 함수DA-ZE✩
void *palloc_get_page (enum palloc_flags flags)
void *palloc_get_multiple (enum palloc_flags flags, size_t page_cnt)
각각 한 페이지, 연속한 page_cnt
페이지 확보하고 포인터 반환한다
할당 실패시 NULL 포인터 반환
flasgs
인자는 이런 것들의 조합이DA-ZE✩
PAL_ASSERT
페이지를 할당하지 못하면 커널 패닉을 발생시킨다
이는 커널 초기화 시점에만 쓸만 하다
PAL_ZERO
반환하기 전에 할당된 모든 바이트를 0으로 초기화한다
설정하지 않으면, 새로 할당된 페이지의 내용 개판난다
PAL_USER
페이지를 유저 풀에서 가져온다
설정하지 않으면 커널 풀에서 할당한다
threads/malloc.h
에 선언되어 있고 임의의 크기의 블록 할당한다
얘도 방법 2가지다
1kB 이하(= 페이지 크기의 1/4 이하) 블록
크기를 가장 가까운 2의 거듭제곱으로 반올림 한다 (단, 최소 16바이트)
이후 그 크기 전용 페이지 만들어 그 안에서만 할당
1kB 초과 블록
오버헤드를 더해 가장 가까운 페이지 크기로 반올림
둘 다 단편화 발생하지만
…
알빠임?
그건 실무 OS에서 신경쓸 일이지
우리는 교육용이라 신경 안쓴다
작은 할당은 상관 없으나 큰 할당 할 경우
페이지 할당자 호출하여야 하기에
너무 큰 거 부르면 단편화 때문에 실패 할 수 있으니
큰 할당(대략 4kB 초과)은 가능하면 줄이자
블록 할당자는 인터럽트 컨스텍트에선 호출 불가다
표준 C 라이브러리 함수들과 인터페이스 동일하다
void *malloc (size_t size)
최소 size
바이트 이상 확보하며 반환
사이즈가 0이거나 못하면 NULL 포인터 반환
void *calloc (size_t a, size_t b)
최소 a * b
바이트 이상 확보하여 반환
블록 내용은 0으로 초기화
a
나 b
가 0이거나 못하면 NULL 포인터 반환
void *realloc (void *block, size_t new_size)
block
을 new_size
로 realloc
한다
실패하면 NULL 반환하고 기존 블록 유효하다
block
NULL이면 malloc()
이고 new_size
가 0이면 free()
다
void free (void *block)
해제되지 않은 block
해제한다