프로세스는 PCB와 Stack, Data, Code, Heap 등 다양한 정보들을 보유중인 독립적인 메모리 공간이 있다.
이 공간은 OS혹은 타 프로세스도 접근할 수 없다.
하지만, OS가 사용하는 메모리 영역은 다른 프로세스가 접근을 할 수 있다. 이러한 특수성이 있다보니 OS에서 메모리를 관리한다.
대부분 인터넷에는 이렇게 정리가 되어있지만, 조금 여태 공부한 내용들을 토대로 정리를 해보자.
프로세스는 간단하게 PCB가 실행되며, OS가 실행한 프로그램의 코드를 읽어들여 이 코드를 프로세스에 할당된 메모리의 Code Segement에 저장을 한다.
그렇게 되면서 전역 변수 및 Static 변수들은 Data Sagment에 할당되며, Heap과 Stack은 초기 메모리주소만 초기화가 된다.
마지막으로 PCB에는 여러 정보가 기록되면 ReadyQueue에 등록이 되고, 스케줄러에 따라서CPU에 할당받기를 기다린다.
즉, 이를 정리해보면 보조 기억장치(하드디스크) → 주 기억장치(메모리) → CPU
크게 이와같은 순서로 등록이 된다.
더 자세히 들어가보면 Register → Cache → Memory → Disk 의 계층이 있지만, 우선 위에 큰 순서로 보자면 프로세스가 CPU에 할당되기 전에는 “메모리”에서 Ready Queue 에서 대기를 하게된다.
자, 프로세스가 CPU에 할당되기 전 메모리에 잔류하고 있다는 사실을 알게 되었고, 과정에서 주 기억장치(메모리)를 꼭 거친다는것을 알게 되었다. 중간 다리 역할을 하며, 터미널같은 존재인 메모리를 잘 관리하지 못하면 한정된 자원을 비효율적으로 사용해 성능이 저하될 수 있다.
예를 들어, 50평의 화장실을 설계하고 있다고 가정을 해보자.
이 50평의 화장실에 여자 화장실과 남자 화장실, 좌변기와 소변기의 위치를 대충 분류하고 아무데나 설치를 하면 어떻게 될까? 공간의 낭비도 심할것이며, 어느곳은 좁고 넓고 등 50평의 공간에 50명의 인원이 동시에 들어갈 수 있으나 20명만 들어갈 수 있는 상황이 나올 수 있다.
위와같은 이유로 메모리 관리가 필요하게 되었으며 이런 메모리 관리를 위한 전략으로 Swapping, Fragmentation, Paging, Segmentation
까지 총 4개가 존재한다.
중기 스케줄러를 다루면서 잠시 나왔던 내용인데, 이는 메모리 관리 전략중 하나이다.
Swap은 맞바꾼다 라는 의미를 가진다.
표준 Swapping 방식으로는 Round-Robin과 같은 스케줄링 알고리즘이 사용되며, CPU할당이 끝난 프로세스는 보조 기억장치로 보내고 다른 프로세스의 메모리를 불러들인다.
보조 기억장치에 있던것을 다시 로딩시켜야 하므로 시간이 길게 걸리지만, 한정된 메모리에 더 많은 프로세스를 실행할 수 있다는 장점이 존재한다 !
장기 스케줄러를 설명하며 나왔던 개념인데, 메인 메모리가 8GB이지만, 10GB의 프로그램을 돌릴 수 있게 해주는 방법이다.
이게 가능한 이유는 위 예시에서는 부족한 2GB는 보조 기억장치(하드디스크)에 저장하고 있다가 필요하면 부분적으로 Swap해주는 방식을 사용하기 때문에 가능하다.
이 두개의 개념은 다르다고 볼 수 있다.
Swapping은 프로세스 단위로 Swap-out Swap-in을 하지만,
VVM은 프로세스의 일부를 Swap-out Swap-in을 한다.
메모리의 공간이 비 효율적으로 사용되어 저장 공간이 낭비되는 현상을 이야기 한다.
이러한 단편화로 생기는 현상은 아래와 같으며, 이러한 단편화는 프로세스를 기준으로 내부 단편화와 외부 단편화로 나뉜다
할당한 영역 중 사용되지 않은 공간으로 인해 공간이 낭비되는것을 의미한다.
즉, 프로세스에게 1GB의 메모리를 할당해 주었지만 실제로 프로세스가 사용하는 메모리는 120MB이다.
이는 페이징 기법에서 나타나는 문제점 중 하나인데, 한 페이지를 너무 크게 할 경우에 생기는 문제이다.
메모리의 여유 공간 즉, 메모리 안의 프로세스간의 간격이 띄엄띄엄 존재해서 실제로 사용할 수 없는 경우를 의미한다.
4GB의 메모리에 1GB의 공간이 남아서 100mb인 프로세스가 메모리에 올라가려고 하는데, 무슨 메모리의 간격이 90MB라서 올라가지 못했다. 90MB가 여럿이 모여 1GB로 표시되긴 하겠지만 실제로는 메모리를 모두 사용하고있는 셈이다..
이는 Segmentation 에서 나타나는 문제점 중 하나이며, 동적 메모리 할당 해제를 자주하면 나타난다.
“하나의 프로세스에는 연속적인 메모리 공간이 할당되어야 한다” 라는 제약이 있다.
하지만, Paging이라는 메모리 관리 기법에서는 이러한 제약을 없애버렸다!
외부 단편화 문제를 해결하기 위해서 나온 개념인데, 이는 크게 물리 메모리와 논리 메모리로 분리가 된다.
물리 메모리는 Frame이라는 고정 크기로 분리
되어있고, 논리 메모리는 프로세스가 점유하는 메모리로, 페이지라는 고정된 크기의 블록으로 분리
된다. 이는 페이지 교체 알고리즘으로 교체가 된다.
이게 살짝 말이 어렵다고 느껴져서 새롭게 정리를 해 보았다.
외부 단편화의 문제점은 각 메모리 사이에 간격이 에매하기때문에 일어났다고 한다.
자 그럼 메모리의 공간이 4000MB면 100MB씩 쪼갠다고 가정을 해보자.이제 프로세스가 메모리에 등록이 된다면, 이 전에 해당 프로세스에서 사용할 수 잇는 메모리의 적정량을 정해준다. 이를 논리 메모리라고 하며 Page 라고도 한다.220MB의 공간만을 사용한다 하면 100MB블록을 3개를 만들어주어 메모리에 적재를 해주며 페이지에는 각 블럭들의 메모리 주소값을 저장해둔다. 여기서 100MB 블록들을 물리 메모리라고 하며 Frame이라고도 한다.
위 예시를 보았을 때 뭔가 이상한점을 느낄 수 있을것이다.
100 / 100 / 100 으로 나누었을 때 한군데에 80이 남는데?
그렇다. 이게 바로 Paging의 문제점인 내부단편화의 발생이다.
페이징에서처럼 메모리를 같은 크기로 나누는것이 아닌 서로 다른 크기의 논리적 단위인 Segment로 분할을 한다.
페이징에서는 메모리 위에 올라간 Frame들은 논리적으로 독립된 내용들이 구분되지 못한다. 쉽게 예시를 들면 120mb인 함수가 100 / 20 이렇게 나뉜다는것이다. 이들을 동작하기 위해서는 Frame들이 Page를 기반으로 동작이 되어야 한다라는 문제점이 있었는데, 이를 해결하기위해 나온 방법이 Segmentation이다.
Segmentation은 위에 말한 문제점을 해결했다싶이 논리적으로 독립된 의미의 세그먼트 단위로 동작하는 메모리 관리 기법이다. 여기서도 프로세스에 할당된 메모리가 분리가 된다. 이 분리된 세그먼트가 디스크립터 테이블
에 저장이 되는데, 이는 운영체제가 관리하는 세그먼트 저장 영역이다.
우리가 여태 공부를 하면서 프로세스는 Code, Data, Stack등으로 난뉘어져있다고 했는데 이렇게 나뉘어지는게 Segmentation기법이 들어갔기 때문에 나뉘어지는 것이다.
220MB의 공간을 할당받는 프로세스는 함수는 각각 50 / 50 / 120 크기이다. 이 크기별로 페이징 기법과 동일하게 프로세스를 나누어 메모리에 배치를 한다.
하지만, 가변적인 크기라는 단점이 있어 여러번의 Swapping이 일어나게 되면 외부 단편화의 문제가 생기게 된다.
이 둘은 각자의 장/단점이 존재하며 Memory Fragment를 해결하기 위해서 나타난 메모리 관리 기법이다.
각 기법의 특징은 아래와 같으며, OS에서는 해당 기법들의 장점들만을 채택하여 Segmentation을 Paging해준다고 한다.
Paging과 Segmentation에 대해서 공부를 했는데, 살짝 의문이 들었다. 메모리를 나눈다고 했는데 이를 어떻게 찾아내고 어떻게 해야 메모리가 인식을 할 수 있을까?
그저 페이지단위로 생각을 하고, 디스크립터 테이블을 보며 비교를 해야하나?
아니다, 이는 이제 MMU에서 다루는 것이다
이는 CPU가 메모리에 접근하는 것을 관리하는 하드웨어 장치이다.
MMU는 CPU코어 안에 탑재되어 가상 주소를 실제 메모리 주소로 변환해주는 장치이며, 이 장치의 “재배치 레지스터" 방식을 이용하게 되면 Paging이나 Segmentation에서 분리된 메모리가 연속된 메모리에 할당된 것 처럼 CPU를 속이게 된다.
Segment당 페이지 테이블이 존재하는것이다.
Segment - table - entry가 Segment의 Base Address를 가지고 있는것이 아닌, Segment를 구성하는 page table이 base address를 가지고 있는것.
segment offset(d), p(페이지번호)/d`(페이지당 오프셋) 별로 메모리의 다른 위치에 올라가게 된다
사실상 메모리 관리에서는 운영체제가 하는 일이 없다 -> 주소 변환은 하드웨어적으로만 이루어진다