메모리 주소의 종류와 주소 바인딩, 변환방식, 관련 용어, 물리적인 메모리 관리에 있어서 두 방식 중 하나인 연속할당을 알아본다.
메모리는 주소를 통해서 접근하는 장치
메모리 주소는 두 종류가 있다.
1. 논리적인 주소
2. 물리적인 주소
물리적인 메모리는 기본적으로 운영체제 커널이 올라가있고,
사용자 프로그램은 디스크에 실행파일로 있다가 실행하려면 메모리에 올라가서 PROCESS가 되는 것이다.
논리적인 주소를 물리적인 주소로 변환하는게 필요하다
누가 해주냐?
하드웨어 지원이 필요하다.
주소 변환을 주소 바인딩이라고 한다. : 논리적 주소를 물리적 주소로 맵핑한다.
언제 주소 바인딩이 이뤄지는지? 3가지
현대에선 2번과(Load time binding) 3번의(RUn time binding) 방식을 사용함
둘다 실행시, 물리적 주소가 매겨지는데
로드 타임 바인딩은: 프로그램이 시작되는 시점에 매겨진다. 그리고 그 주소가 안바뀐다.
런 타임 바인딩은: 프로그램이 시작될 때 주소바인딩이 이뤄졌다. 물리적 주소가 결정됐는데 프로그램이 실행되는 도중에 주소가 바뀔 수 있다.
절대 코드: 주소변환이 필요없다. 그 코드를 그대로 메모리에 올려서 실행시켜도 되는 코드
relocatable code : 물리적인 메모리의 위치가 바뀔 수 있는 코드다. 메모리 상의 위치가 컴파일 할 때 이미 정해졌나 아니면 재배치가 가능하냐 (로드타임 바인딩, 런타임 바인딩)
cpu가 바라보는 주소는 논리적인 주소일까? 물리적인 주소일까? cpu는 하드웨어고, 기계장치니까 물리적 주소를 바라볼 것 같지만, 논리적 주소다.
cpu는 메모리 접근을 할 때마다 그때그때 변환을 해서 메모리 접근을 해야 한다.
주소변환을 하는 하드웨어 : MMU
간단한 mmu 하드웨어로 메모리 주소 변환 방식
사용자 프로그램은 당연히 논리적 주소를 본다. 물리적 주소는 알수도 없고 알필요도 없다. 실행될 때 cpu도 논리적 주소를 본다. cpu가 메모리 접근을 할 때 mmu 하드웨어에 의해서 주소 변환을 하고 그 결과 물리적 주소를 얻어서 접근을 하는 것이다 !!!
프로그램을 하나 만들면 컴파일이 되고, linking이 돼서 실행파일이 만들어지는 것이다.
프로그램을 만들 때 내가 다 코드를 만드는 것이 아니다. 내가 만든 함수도 있고, 라이브러리를 쓰기도 한다. 라이브러리는 내가 만든게 아니지만 실행 파일이 만들어지면 내 코드 안에 고스란히 포함된다. 내가 만든 코드와 라이브러리가 연결이 돼서 실행파일이 만들어지는 것이다. 라이브러리를 연결하는 작업이 => linking이다.
그래서 언제 linking이 되는데 ?
1. static linking
다이나믹 로딩과 의미가 같아.
근데 역사적으로 용어의 의미의 차이가 있는 것이다.
초창기에는 메모리 크기가 작아서
프로그램 하나 모두를 메모리에 올리는 것이 불가능.
개발자가 지금은 이걸 메모리에 올리고
다음에는 메모리에 있던걸 다 내리고 다른거 올리고
수작업으로 다 진행했었다.
개발자한테 엄청난 짐이다.
오리지널 스와핑: 메모리에서 프로그램을 통째로 쫓아낸다.
중기 스케줄러: 메모리에 너무 많은 프로그램이 올라가 있으면 비효율적이기 때문에 일부 프로세스를 골라서 메모리에서 통째로 쫓아내는 것. => 쫓아낸 프로세스는(swap out) suspended 상태가 됐다. - swap in이 되면 ready, run, blocked 상태가 되는 것이다.
어떤 프로세스를 쫓아낼 것인가?
-cpu 우선순위가 낮은 순 : 당장 실행될 가능성이 낮은.
swapping이 지원되려면 compile 바인딩과 로드타임 바인딩은 비효율적이다. 메모리가 비어있는데도 꼭 그 메모리를 고집하기 때문에! run time 바인딩은 메모리 위치가 바뀌어도 되기 때문에 좋음!
그런데, 지금 설명드리는 내용은 위 내용과 상반된다.
스와핑에서는 메모리에 프로세스 주소공간을 통째로 쫓아내고 읽어드리는 양이 많기 때문에 스와핑 i/o에서는 실제로 데이터를 transfer하는 시간이 스와핑의 상당 부분 시간을 차지한다.
현대적인 운영체제는 통째로 쫓아내는 스와핑도 이용하긴 하지만, 부분부분을 쫓아내는 것도 있다. 일부 페이지만 swap out 됐다.하는 것도 있음
//지금부터는 물리적 메모리의 관리 기법을 설명하겠습니다 !
낮은 주소 영역에는 운영체제 커널이 항상 상주, 나머지 영역에는 사용자 프로그램이 올라간다. 이 영역을 어떻게 관리 할건가?
연속할당: 프로그램이 쪼개지지 않고, 통째로 올라가는것
=> 주소변환이 비교적 간단했다. 프로그램 시작위치가 어딘지만 알면 얼마큼 떨어져있는가를 더해줬으면 됐었다.
현대 운영체제는 전혀 쓰고 있지 않지만 전형적으로 설명을 하는 것 !
고정분할방식: 메모리를 미리 분할을 해서 각각에 할당하는 방식
낭비되는 메모리=> 내부 조각 => 비효율적이다 !
외부조각은 아무도 사용하지 못한다 => 외부 조각 => 비효율적!
가변 분할 방식: 미리 메모리를 할당하지 않고, 메모리를 차례로 프로그램이 쓴다.
프로그램 b가 종료 되면 => 비어있다. 이건 외부조각 => 다른 프로그램이 올 수 있다. d가 들어가야 하는데 외부 조각이 너무 작아서 못 들아간다. => 그래서 c다음 메모리를 d가 써야 한다.
할당이 됐는데 사용못하는 내부조각은 없다 !
근데 마침 다른 프로그램이 외부 조각에 들어갈 수 있는 크기 일 수도 있으니, 낭비가 안된다 ! 개념적으로만 이해하자 ~~~
조각들은 비어있는 메모리 공간이다 !
프로그램이 실행될 때 비어있는 hole 중 어디다가 옮길 것인가?
=> 적어도 메모리 크기가 프로그램 크기보다 같거나 커야한다.
=> 방법이 3가지다 알아보자!
1) first-fit
2) best-fit
3) worst-fit
빈공간이 있는데 활용이 안될 때
: 빈공간을 모아서 큰 홀을 만들자 !
외부 조각들을 한데 모아서 프로그램이 들어갈 수 있는 큰 홀로 만들어보자!