단편화(Fragmentation)

RAM에서 공간이 작은 조각으로 나누어져 사용 가능한 메모리가 충분히 존재하지만 할당이 불가능한 상태이다.

단편화는 내부, 외부 단편화가 있다.

내부 단편화(Internal Frammentation)

메모리를 할당할 때 프로세스의 메모리가 필요한 양보다 더많이 할당되어서 프로세스에서 사용하는 메모리 공간이 낭비 되는 현상이다.

운영체제가 프로세스에 30mb를 할당 해줬을때, 사실상 20mb만 사용하고 있을 경우 내부 단편화가 10mb만큼 발생한다.

30mb의 빈공간에 20mb크기의 프로세스4가 할당되면 

10mb의 내부 단편화가 일어나게 됩니다.

외부 단편화(External Fragmentation)

프로세스들의 메모리를 할당하고 난 다음 아주 작은 크기로 남은 조각들이 생겨 사용할 수 없는 작은 메모리 공간들이 생길수 있는데. 이 공간들을 합쳐서 새로운 프로세스가 요구하는 메모리의 크기를 할당할 수 있음에도 불구하고 연속적인 공간이 아니라서 할당을 하지 못하는 경우다.

10mb + 10mb = 20mb의 크기가 남아있지만
20mb의 메모리가 필요한 프로세스4 는 할당 될 수 없다.

문제 해결 방법

문제 해결 방법으로는 페이징(Paging), 세그멘테이션(Segmentation), 메모리 풀(Memory Pool) 이 있다.

페이징(Paging)

가상메모리사용, 외부 단편화 해결, 내부 단편화 존재

보조기억장치를 이용한 가상메모리를 같은 크기의 블록으로 나눈 것을 페이지라고 하고 RAM을 페이지와 같은 크기로 나눈 것을 프레임이라고 할 때,

페이징 기법이란 사용하지 않는 프레임을 페이지에 옮기고, 필요한 메모리를 페이지 단위로 프레임에 옮기는 기법.

페이지와 프레임을 대응시키기 위해 page mapping과정이 필요해서 paging table을 만든다.

페이징 기법을 사용하면 연속적이지 않은 공간도 활용할 수 있기 때문에 외부 단편화 문제를 해결할 수 있다.

대신 페이지 단위에 알맞게 꽉채워 쓰는게 아니므로 내부 단편화 문제는 여전히 있다.

* 페이지 단위를 작게하면 내부 단편화 문제도 해결할 수 있겠지만 대신 page mapping 과정이 많아지므로 오히려 효율이 떨어질 수 있다. 

세그멘테이션(Segmentation)

가상메모리사용, 외부 단편화 존재, 내부 단편화 해결

페이징기법에서 가상메모리를 같은 크기의 단위로 분할했지만 세그멘테이션기법에서는 가상메모리를 서로 크기가 다른 논리적 단위인 세그먼트로 분할해서 메모리를 할당하여 실제 메모리 주소로 변환을 하게 된다.

각 세그먼트는 연속적인 공간에 저장되어 있다.

세그먼트들의 크기가 다르기 때문에 미리 분할해 둘 수 없고 메모리에 적재될 때 빈 공간을 찾아 할당하는 기법이다.

마찬가지로 mapping을 위해 세그먼트 테이블이 필요하다.

(각 세그먼트 항목별 세그먼트 시작주소와 세그먼트의 길이 정보를 가지고 있음)

프로세스가 필요한 메모리 만큼 할당해주기 때문에 내부단편화는 일어나지 않으나 여전히 중간에 프로세스가 메모리를 해제하면 생기는 구멍, 즉 외부 단편화 문제는 여전히 존재한다.

메모리 풀(Memory Pool)

가상메모리사용, 외부 단편화 해결, 내부 단편화 해결

필요한 메모리 공간을 필요한 크기, 개수 만큼 사용자가 직접 지정하여 미리 할당받아 놓고 필요할 때마다 사용하고 반납하는 기법

메모리 풀 없이 동적할당과 해제를 반복하면 메모리의 랜덤한(실제로는 알고리즘에 의한) 위치에 할당과 해제가 반복되면서 단편화를 일으킬 수 있겠지만 미리 공간을 할당해놓고 가져다 쓰고 반납하기 때문에 할당과 해제로 인한 외부 단편화가 발생하지 않는다.

또한 필요한 크기만큼 할당을 해놓기 때문에 내부 단편화 또한 생기지 않는다.

하지만 메모리 단편화로 인한 메모리 낭비량보다 메모리 풀을 만들었지만 쓰지 않았을 때 메모리 양이 커질 경우 사용하지 않아야 한다.

메모리의 할당, 해제가 잦은 경우에 메모리 풀을 쓰면 효과적이다.

미리 할당해놓고 사용하지 않는 순간에도 계속 할당해놓으므로 메모리 누수가 있는 방식이다.

메모리 풀(Memory Pool) 구현 방법

- 큰 메모리 블록(페이지)을 힙으로 부터 할당
- 할당 받은 페이지를 각 객체의 크기의 블록으로 나눔
- 각 객체를 위한 블록을 순차적으로 링크
- 이 때 현 시점에서 할당할 블록을 특정 포인터가 가리키게 함
- 메모리 요청이 생기면 현재 헤더 포인터가 가리키는 블록을 돌려준다.
- 할당이 일어난 후 헤더 포인터는 할당 직전에 가리키던 블록이 가리키던 블록을 가리킨다.
- 사용되던 메모리가 해제되어 메모리 풀로 돌아올 경우 헤더 포인터는 그 블록을 가리키고 방금 전까지 헤더 포인터가 가리키던 블록을 돌아온 블록의 다음 포인터가 가리키게 한다.

 

출처 : https://jeong-pro.tistory.com/91

+ Recent posts