Memory Segmentation and Free-Space Management


1KB(1 키비 바이트) = 1024B (B는 보통 생략)
-
4KB = 4096B → 4200 - 4096 = 104 이값이 offset이 된다!
- Segment fault (heap밑의 사용하지 않는 영역을 참조하게 되면 발생함, 불법적인 접근!)
- 또한, 세그먼트의 크기가 커지거나 줄어들때 어떻게 해야될까?
- malloc을 통한 동적할당은 heap세그먼트에 할당된다. 감당할 수 있는 크기가 정해져있지만 이 크기를 넘어서 할당하는 경우엔 sbrk() 시스템콜을 통해 heap세그먼트의 크기를 증가시키고, 변화된 크기 만큼 다시 base-bound레지스터 값을 등록한다.

- 가상주소의 상위 N비트를 가지고 세그먼트를 분류함 → (N = 1~4까지 가능)
- 00 → code, 01 → heap, 10 → stack 등등 4200에 해당하는건 → segment bit이 01(밑의 그림에서 확인 가능)이므로 heap

-
Stack 세그먼트
- 위로 자란다 → grow positive = 0 , segment의 끝주소가 base address
- 아래로 자란다 → grow positive = 1 , segment의 시작주소가 base address
- 예시에서 힙은 32K(base)가 세그먼트 위치상으로 시작의 주소
- 예시에서 스택은 28K(base)가 세그먼트 위치상으로 끝의 주소

-
코드에 대한 공유
- 주소공간에 있는 세그먼트 들은 공유될 수 있다.
- 같은 프로그램에는 코드 섹션이 같기 때문에 데이터가 공유될 수 있는데 이때 데이터 간의 덮어쓰기가 발생하면 안된다. → 보호 bit를 이용(read, write, execute 3개의 비트 이용)
- 예시 : 크롬 창 2개를 열어도 같은 프로그램이므로 둘다 같은 주소에 있는 데이터를 이용하는데 서로 덮어쓰기가 발생하면 안됌
- 보호 비트 : rbit 1칸 | wbit 1칸 | xbit 1칸 → 얘네들로 데이터가 사용됐는지 표시

-
Fine-Grained and Coarse-Grained segmentation
- fine : 세분화된 작업 (하나의 작업을 여러단위로) → 여러개의 세그먼트를 나눈것
- 이는 일부 초기 시스템에서 주소공간을 더 유연하게 만들어준다.
- 많은 세그먼트를 지원하려면 하드웨어는 segment table이 요청된다.
- coarse : 덩어리식 작업 (하나의 작업을 하나의 작업으로) → 큼지막한 세그먼트(code, heap, stack) 등으로 만 나눈것
-
외부 단편화 external-fragmentation
- 프로세스 별로 메모리할당을 받으면 물리주소에 segment가 생길 것이고, 이는 중간중간 할당 받아 free space의 구멍이 뻥뻥 뚫려 있게 된다. 이는 새로운 세그먼트의 할당을 어렵게 만든다. (프로세스가 다른 프로세스의 메모리를 참조하면 안되므로) 이를 외부 단편화라고 한다!
- 해결책 → compaction : 물리주소의 할당중인 세그먼트를 재조정을 통해 압축

- 컴팩션은 비용이 많이 든다.
- 프로세스 실행 중지, 데이터 어디로 복사할지에 대한 문제, 세그먼트 레지스터값(base-bound) 변경
-
Splitting 스플릿

- free 스페이스가 2부분이있는데 1byte를 할당 요청 받음 → free space의 크기는 10바이트로 1바이트보다 커서 수용할 수 있으므로 10 ⇒ 1/9로 쪼개서 1byte를 할당하고 9byte를 다시 free space로 여겨 free list에 반환!
- Coalescing 코알레싱(한국어로 통합)
-
그렇다면 위의 예시에서 사용자가 10byte보다 큰 메모리를 요청하면 free list는 그에 상응하는 free space를 찾지 못할 것이다.
-
해결책 → Coalesing : 사용 이후 반환되는 free space가 기존의 free space들과 주소가 가까운 경우 1개의 free space로 통합!
- 컴팩션 : 할당된 segment를 통합 / 코알레싱 : free space를 통합

-
할당된 부분의 사이즈를 추적하는 방법
-
ptr = malloc(20) 으로 할당 후에 → free(ptr)일반적으로 이렇게 해줌
-
free는 size 매개변수를 넘기지 않았는데 어떻게 크기를 알 수 있을까?
- malloc으로 할당된 메모리의 header가 size의 크기를 담고 있다.
- head = 8byte (int 4byte, int magic 4byte)(20을 불렀지만 실제론 28byte)


- magic넘버는 고유성검사를 위한 것(free하는 메모리가 정말 이 메모리가 맞아?)
- malloc으로 부른 크기 + 헤더파일의 크기 8byte = 할당된 메모리의 실제 크기
- 헤더 포인터를 찾기 위한 간단한 계산

-
Embedding A free list
- free list도 공간의 size와 next노드를 가리키는 포인터로 공간을 만들 수 있다.

-
mmap시스템 콜을 통해 첫번째 free list의 헤드 노드를 할당 받을 수 있다.
- free list 노드의 사이즈 = int4byte + 포인터4byte = 8 + 공간의 크기

-
힙 세그먼트를 할당한 후에 크기를 늘리고 싶을때
- sbrk() 시스템콜로 확장!(sbrk는 힙의 끝위치를 반환하는 시스템콜)
- 할당된 공간을 변경하는 것은 불가능하다. 가상주소의 힙 세그먼트를 늘려 물리주소의 늘린 공간을 다른 공간에 추가 할당하는 것은 가능하다!

-
free space 관리 기본전략
- best fit : 할당요청받은 공간보다 살짝 더 큰 공간을 찾아 그 중 가장 작은 공간을 반환
- worst fit : free list중에서 가장 큰 공간을 찾아 할당
- 남아있는 공간의 평균 크기가 고루 분포될 확률이 높아 best option이다!
- best fit / worst fit의 결과 (worst fit의 경우 10, 15, 20으로 공간크기가 고루 비슷함)
- first fit : free list중에서 요청에 충분히 큰 첫 번째로 보이는 공간 찾기(free space는 위에서부터 탐색하므로)
- next fit : 이전 공간을 할당해준 위치를 탐색 위치로 정하여 요청에 충분히 큰 첫 번째 공간 찾기
-
Slab & buddy