메모리는 주소를 통해서 접근하는 매체이다.
메모리는 2가지 주소료 표현할 수 있다.
논리적주소는 프로그램이 시작되면 독자적인 공간이 생성된다.
프로그램,프로세스 마다 가지는 메모리주소가 논리적인 주소이다.
또는 가상주소라고도 한다.
물리적주소는 실제로 존재하는 메모리에 올라가는 위치이다.
물리적인 메모리안에 하위주소에는 운영체제 커널의 주소가, 상위주소에는 여러 프로그램이 섞여서 올라가게 된다.
프로그램마다 0번지로 부터 시작하는 독자적인 논리주소를 가지지만 이게 실행이되려면 물리적인 위치에 올라가야되고, 논리적주소가 물리적 주소로 변화되야된다. 이렇게 주소변환이 이루어지는 것을 주소 바인딩이라고 한다.
다시말해 프로그램이 실행이 되기 위해서 물리적 메모리의 어디에 올라갈지 메모리주소를 결정하는 것을 주소 바인딩이라고 한다.
symbolic address
프로그램 코드를 작성시 우리는 변수나 함수를 이용한다. 변수나 함수를 이용하면 변수나 함수에 주소값이 저장되게 된다. 우리는 변수를 지정할 때 몇번지 부터 몇번지 이렇게 특정해서 주소를 지정하지 않는다. 변수나 함수는 주소값을 가지게 되는데, 프로그래머 입장에서는 이를 symbolic address라고 한다.
프로그래머가 메모리를 사용하지만, 숫자가 아닌 symbol로 된 것을 사용하고 컴파일이 되면 숫자로 된 주소로 변경되게 된다.
이게 실행이 되려면 물리적 주소로 변경되야 하고 언제 변경되는가? 크게 3가지로 나눌수 있다.
그렇다면 주소 바인딩은 언제 발생할까? 언제 주소가 결정될까?
Complie time binding
컴파일이 될때 변환
Load time binding
실행이 시작될 때 변환
Run time binding
프로그램이 실행된 이후에도 물리적 위치가 변경될 수 있는 변환
물리적위치가 결정되는 것을 주소바인딩이라고 하고 3가지로 나뉜다.
Complie tim binding은 컴파일 시점에 이미 주소바인딩이 된다.
비효율적이다. 지금의 컴퓨터 시스템에서는 사용하지 않는다. 컴퓨터에서 하나의 프로그램만 실행되던 때는 컴파일 시 물리적 위치를 결정하는 것을 사용했다.
논리적은 주소가 물리적 주소로 고정되기 때문에 절대 코드라고 한다.
메모리에 올라갈 위치를 바꾸기 위해서는 컴파일을 다시 해야한다. 그래야지 다른 위치로 변경이 가능하다. 그렇지 않다면 변경이 불가능하다.
Load time binding은 프로그램이 실행이되서 메모리에 올라갈 때 바이딩이 된다. 논리적인 주소만 정해두고서 실행이 될때 메모리의 비어있는 곳을 확인해서 물리적메모리로 바인딩한다.
재배치 가능코드이다. 항상 특정위치에 올라가는 것이 아니라 비어있는 위치로 올라가게 된다.
Run time binding은 실행시에 주소가 결정되는 것은 Load time binding와 같으나 이 주소가 실행 중에 바뀔 수 있다.
실행되는 도중에 물리적 위치가 바뀔 수도 있다. 메모리에서 쫒겨 날 수도 있고, 쫒겨나고나서 다시 올라갈때 비어있는 것에 다시 올리다보니 바뀔 수 있다.
프로그램 실행중에도 주소가 변경 될 수 있다.
cpu가 메모리 주소를 요청할 때마다 주소를 확인해서 알려주어야 한다.
그렇기 때문에 Run time binding은 하드웨어 적인 지원이 필요하다.(MMU)
cpu가 바라보는 주소는 물리적 주소일까, 논리적 주소일까?
cpu가 바라보는 주소는 하드웨어 이지만 논리적주소를 바라보게 된다.
컴파일된 코드 자체의 위치는 물리적위치로 올라갈때 변경되지 않는다. 그렇기 때문에 논리적 위치를 바라보게 된다.
위 그림을 보게되면 실행파일의 주소가 물리적위치로 올라간 뒤에도 그 안의 주소값은 변경되지 않는다. 그렇기 때문에 cpu는 논리적주소를 바라보고 있다고 할 수 있다.
Run time binding이 지원되려면 하드웨어적인 지원이 필요하다고 했다.
Run time binding은 물리적 위치가 계속 해서 바뀌는 주소변환방식이다.
그렇기 때문데 올라 갈때마다 어디에 올라가있는지 주소변환을 알려줄 하드웨어가 필요한데 이를 MMU라고 한다.
MMU는 두개의 레지스터를 이용해서 주소를 변환한다.
basic register에다가 물리적메모리에 올라갈때 주소가 시작되는 위치를 저장해둔다.(프로그램의 시작위치를 저장해둔다.)
basic register에 논리적위치(346)을 더해서 물리적 위치로 변환한다.
limit register는 프로그램의 최대 크기를 저장한다.
예를 들어 악의적으로 메모리 주소 접근해서 14000 + 4000(18000)번지를 요청하는 것을 막기 위해서 사용하는 것이다.
남의 프로그램 메모리를 보려고 하는 시도이기 때문에 막아야 한다.
사용자 프로그램은 logical address만 다루고 실제로는 물리적 주소는 볼 수 없고 알 필요도 없다.
프로그램은 메모리에 올라가야지 실행이 되는데, 이때 메모리에 올리는 방법은 정적인 방법과 동적인 방법이 있다.
정적이라는 것은 프로그램이 실행시 통째로 올리는 것을 말하며, 동적이라는 것은 필요에 따라 메모리에 올리는 것을 말한다.
Dynamic Loading이란 말 그대로 동적로딩을 의미한다.
해당 루틴이 불러 질 때마다 메모리에 load하는 것이다.
프로그램이 실행될 때 통째로 올려놓는 것(정적로딩)이 아니라 필요에 따라 메모리에 올리는 것을 의미한다.
현재 컴퓨터 시스템은 필요한 부분만 메모리에 올라가고 필요없으면 쫒아내고 하는데, 이는 운영체제가 관리하는 페이징시스템에 의해 이루어지는 것이다.
페이징시스템에 의해서 되는 것은 운영체제에 의해서 이루어지는 것이고,
동적로딩이라고 하면 프로그래머가 직접 동적로딩을 구현하는 것을 의미한다.
직접 손수 다 하는 것이 아니라 운영체제가 라이브러리로 지원해주는 것을 이용해서 동적로딩을 구현하는 것이다.
현재 시스템에서 이루어지는 페이징시스템과 동적로딩은 다르다는 점을 알자!!
프로그래머가 명시적으로 하는 것이 본래의 동적로딩이지만, 운영체제에 의해서 실행되는 동적로딩과 비슷한 것도 동적로딩이라고 섞어서 불리게 되었다.
내용을 보면 동적로딩과 비슷하다.
Overlay는 초창기 컴퓨터 시스템에서 메모리 크기가 작기 때문에 프로그램하나를 메모리에 올리는 것도 불가능했다. 그렇기 때문에 프로그램을 쪼개서 필요한 부분을 프로그램머가 수작업으로 올리고 내리고 했다. 운영체제의 지원이 없이 프로그래머가 직접했다.
프로세스를 메모리에서 통째로 하드디스크로 쫒아내는 것을 의미한다.
프로세스를 일시적으로 메모리에서
메모리에 너무 많은 프로그램이 올라와있으면 시스템이 비효율적이 되기 때문에, 중기스케쥴러가 일부 프로그램을 골라서 통째로 메모리에서 디스크로 쫒아내는 일을 한다. swapping의 개념과 관련된다.
cpu우선순위가 낮은 프로세스를 쫒아낸다.
swapping시스템이 지원이 되기 위해서는 바인딩과 연관해서 생각해보아야 한다.
만약 바인딩의 complie time binding, load time binding방법이라면 swapping된 경우라면, 이전 주소 그대로 올라와야한다. 다른 메모리가 비어 있어도 원래의 물리적 위치로 다시 올라와야 하기 때문에 swapping의 효과를 십분 발휘할 수 없게 된다.
swapping이 효율적으로 사용되기 위해서는 run time binding이 지원되어야 한다. swapping 후에 메모리의 위치가 변경될 수 있어야 한다.
최근에는 페이징 시스템에서 프로그램 전체가 쫒겨나는게 아니라 프로그램의 주소 공간이 잘게 쪼개져서 일부 페이지가 메모리에서 쫒겨나고, 일부는 올라가는 것 중에서 일부가 쫒겨나는 것을 swap out 됬다고 쓰기도 한다.
본래의 개념은 프로그램을 구성하는 주소공간을 모두 쫒겨나는 것을 의미한다.
프로그램을 작성 후에 컴파일 하고 링크해서 실행파일을 만들게 된다.
라이브러리가 프로그램의 실행파일의 코드에 포함되는 것을 정적 링크라고 한다.
라이브러리가 실행시 연결되는 것을 동적 링크라고 한다.
다이나믹 링크을 해주는 것은 shared 라이브러리라고 부른다.
shared 오브젝트
낮은 주소부분에 os커널, 높은 주소부분에는 사용자 프로그램이 올라가게 된다.
사용자 프로그램이 올라가는 부분을 관리하는 방법을 크게 2가지로 나눌수 있다.
프로그램이 메모리에 올라갈때 연속적인 공간에 올라가는 것을 연속할당이라고 한다.
프로그램을 구성하는 주소 공간을 잘개 쪼개서 일부는 다른쪽 일부는 또 다른쪽에 올라가는것을 불연속할당이라고 한다.
현재의 시스템은 불연속할당을 사용하고 있다.
프로그램의 주소공간을 같은 공간의 페이지로 쪼개서 페이지 단위로 메모리의 여기저기에 올리고 내리는 기법을 페이징 기법이라고 한다.
연속할당에는 다시 고정분할방식과 가변분할방식으로 나뉘게 된다.
고정분할방식
고정분할방식은 프로그램이 들어갈 사용자 메모리 영역을 미리 파티션으로 나누어 두는 것을 의미한다.
프로그램의 크기에 따라서 분할된 곳에 들어가는게 다르게 된다.
그러다보니 낭비되는 메모리 조각이 발생하게 된다.(외부조각과 내부조각)
가변분할방식
가변분할방식은 프로그램이 들어갈 사용자 메모리 영역을 미리 나누어 두지 않는 것을 의미한다. 프로그램이 실행될 때마다 차곡차곡 순서대로 올리는 것을 의미한다.
가변분할을 사용해도 프로그램의 크기가 다 다르므로 프로그램의 실행되고 종료되고 하다보면 외부조각이 생길 수 있다. 내부조각은 생기지 않는다.
외부조각이 생겨서 메모리에 Hole(홀)이 생길수 있다.
외부조각이란 프로그램을 올리려고 하는데, 올리려는 프로그램보다 메모리의 분할이 작은 경우를 의미한다.
내부조각은 프로그램의 크기가 분할보다 작은데, 그 안에 남는 메모리 낭비 공간을 내부조각이라고 한다.
분할이 작아서, 프로그램과 분할의 크기가 달라서 생기는 문제가 있다.
운영체제는 물리적인 메모리에서 어느부분은 프로그램에 의해서 사용되고, 어느부분은 사용되지 않는지 관리하고 있어야 한다.
Hole중에서 어디에다가 프로그램을 넣을 것인지 결정해야 한다.
어느 hole에다가 size가 n인 프로그램을 넣을지를 결정해야 한다.
first-fit size가 맞는 첫번째 hole에 할당
best-fit hole을 다 살펴보고서 size와 제일 잘 맞는 곳에 할당
worse-fit 가장 큰 hole에 할당 전체 hole을 탐색해야 한다.
hole들을 미뤄서 한 군데로 모을 수 있는데 이를 compaction이라고 한다.
작은 이동을 통해서 큰 hole을 만드는 것이 효율적이다. 하지만 어떤 hole을 이동시킬 지 결정하는 것과 실제 이동시키는 것 등의 간단하지는 않다.
가변분할방식은 중간중간에 생기는 hole이 있기 때문에 어디에 올릴것인가. hole을 밀어서 compaction하는 방법도 있다.
불연속할당에는 Paging기법, Segmentation기법, Paged segmentation기법이 있다.
paging기법
프로그램을 구성하는 주소공간을 같은 크기의 페이지로 자르는 것을 의미하며, 페이지 단위로 물리적 메모리에 올리거나, backing store에 내리는 행위를 하는 것을 의미한다.
프로그램을 구성하는 주소공간을 같은 크기의 페이지 단위로 자르는것과 같이, 물리적 메모리의 사용자 프로그램이 들어갈 수 있는 공간도 페이지단위가 들어갈 수 있는 크기로 잘라둔다.
페이지 프레임이라고 한다.
페이지 프레임이란 페이지가 들어갈 수 있는 공간, 물리적 메모리의 공간이다.
페이지프레임 하나하나에 페이지가 올라갈 수 있다.
hole들을 미루어서 한군데 두는, hole의 크기가 균일하지 않아서 발생하는 등의 hole문제가 발생하지 않는다. 대신에 주소변환이 복잡해 진다.
주소변환을 페이지 별로 해야되기 때문에 바이딩이 어려워 진다.
페이지 테이블을 이용해서 주소변환을 한다.
segmentation기법
프로그램의 주소공간을 의미 있는 단위로 자르는 것을 의미한다.
프로그램의 주소공간이라는 것이, 코드 데이터 스택으로 구성된다.
코드 세그먼트, 데이터 세그먼트, 스텍 세그먼트로 쪼개서 각 각의 세스먼트를 필요에 따라 물리적 메모리의 다른 위치에 올려 둘 수 있는 것을 의미한다. 더 잘게 쪼 갤수도 있다.
세그먼트는 의미단위로 짜르기 때문에 크기가 동일하지 않다.
dynamic storage-allocation problem이 발생할 수 있다.
paged segmentation기법