반응형
- 시분할 시스템에서는 여러 프로세스들이 동시에 수행된다. 즉, 여러 프로세스들이 메인메모리 상에 공존하고 있어야 한다. 제한된 용량의 메인메모리에서 이를 제대로 실현시켜 주어야 각 프로세스들의 성능도 저하되지 않고 CPU의 이용률도 올라가게 된다.
- 이런 맥락에서 이번 장부터는 메인메모리를 관리하는 다양한 기법들을 알아볼 것이다. 분할기법, 페이징기법, 세그먼테이션 기법 등이 그 예이다. 더 중요하다고 할 수 있는 가상 메모리 기법은 다음 파트에서 다룰 것이다.
- 다양한 기법들을 공부하기 전에 먼저 컴퓨터 시스템의 주소체계에 대한 이해가 필요하다. 따라서, 이와 관련된 개념들인 논리주소, 물리주소, 주소결속 등에 대하여 알아볼 것이다.
프로그램이 돌아가는 과정
int g_a;
main() { … g_a++; printf(g_a); … }
- 리눅스에서 이러한 코드의 프로그램을 돌린다고 가정해보자.
- gcc main.c 구문을 통해 컴파일을 하고 나면, a.out이라는 실행파일이 생긴다. 해당 파일을 ./a.out으로 실행할 수 있을 것이다.
- 좀 더 복잡한 프로그램이라면 main.c 말고 여러 파일로 나누어서 프로그램을 만들기도 하겠지만, 결국은 각각의 파일들이 컴파일되어 오브젝트 파일로 존재하게 될 것이고, 이러한 오브젝트 파일과 링크하여 a.out 같은 하나의 실행가능한 형태로 만들어진다.
- 이렇게 실행 가능한 파일은 메인 메모리로 탑재가 가능하므로 '로더블 파일'이라고 한다. 리눅스에서는 로더블 파일의 포멧으로 주로 ELF(Executable and Linkable Format)를 사용한다.
- 아무튼 이러한 a.out을 수행시킨다고 했을 때, 이 로더블 파일은 통상적으로 하드디스크에 저장되어 있을 것이다. 이것을 메인메모리로 탑재하는 것은 '로더'이다. 이전에 배운 exec 시스템 콜은 파라미터로 지정한 오브젝트 파일을 로딩하는데, 이 때 불리는 것도 '로더'이다.
- 프로그램 내의 printf문은 개발자가 직접 프로그램한 것이 아니다. 따라서 시스템 라이브러리와 링크하여 로드한다. 이렇게 로드된 프로그램은 프로세스 상태 천이를 거치면서 일생을 지내게 된다.
- 여기서 포인트는 'g_a' 변수이다. 기본적으로 변수는 메인메모리의 한 곳을 차지하게 된다. 이 변수의 주소는 하나로 이야기하기 어렵다. a_out 이라는 로더블 파일로 존재할 때 해당주소는 '논리주소'이다. 즉, 프로그램 시작주소를 0번지로 설정한 상대적인 주소라는 것이다. 메인메모리에 탑재된 이 후도 마찬가지이다. 예를들어 g_a 변수의 논리주소가 346번지라 하면, 메인 메모리에 탑재될 때는 주소가 매번 달라진다.
- 어느 한 시점에 메모리에 탑재된 g_a 변수의 메모리 주소가 14346번지라면 해당 번지를 '물리주소'라고 한다. 논리주소는 하나지만 물리주소는 매번 로딩될 때마다 달라진다.
- 수행시점에 논리주소가 물리주소로 바뀌는 과정이 요구된다. 이처럼 논리주소가 물리주소로 확정되는 과정을 주소할당 혹은 주소결속(address binding)이라고 한다.
논리주소와 물리주소
int g_a;
main() { … g_a++; printf(g_a); … }
- 논리주소공간은 지금까지 배웠던 메모리 공간과 유사하게 구성된다. 제일 아래가 0번지로 논리 주소의 기준점이 된다. 그리고 그 위에 text부분인 코드가 들어가게 된다. 그리고 그 위에 전역변수 영역이 존재하게 된다.
- 앞서 확인한 g_a 변수가 논리주소 346번지에 존재한다고 하면, text 영역에는 LOAD @346 / INC / STOR @346이 생성되어 텍스트 영역에 들어가 있게 된다. 이러한 논리주소는 컴파일 및 링크 과정을 통해 결정된 것이다. @는 메모리 주소를 나타내는 표기라고 하자.
- 논리주소를 그대로 차용해선 안된다. 해당 프로그램이 실제 메인 메모리 어느 위치부터 탑재되었는지 알아야 한다. 그리고 해당 위치부터 논리 주소를 적용하는 것이다. 예를 들어 위 프로그램이 메인 메모리의 14000번지부터 탑재되었다고 하면, 논리주소 0번지가 물리주소 14000번지가 되는 것이고, g_a 변수는 14346번지에 존재하게 될 것이다.
- 이러한 과정이 주소결속이다. 주소결속은 한번에 이루어지지 않고 하드웨어 지원을 받아 실행시간에 이루어진다. 즉, 명령어 하나하나가 실행될 때마다 주소변환이 이루어진다. 이 때 사용되는 하드웨어가 ' MMU(Memory Management Unit)의 재배치 레지스터'인데, 해당 레지스터에 물리주소의 시작점이 기록되어 있어 해당 값에 논리주소값을 더해 물리주소값을 계산한다. 해당작업은 하드웨어적으로 이뤄서 시간이 걸리지 않는다.
주소 결속 시점의 다양성
- 앞서 주소결속이 실행시간 내에 이루어진다고 했지만, 사실 꼭 그렇지는 않다. 어떤 시스템은 개발자가 프로그램을 실행할 때 직접 물리주소를 지정해버릴 수도 있다. 하지만 이는 어셈블리어로 코딩을 했던 오래 전 이야기이다.
- 이러한 오래 전 이야기를 제쳐둔다면, 주소 결속은 컴파일시점, 적재시점, 실행시점 3가지 시점에서 이루어질 수 있다.
- 컴파일시점 바인딩 : 컴파일러가 물리주소를 생성하는 것이다 .예를 들어 사용자 프로세스가 특정 물리주소 i번지에서 시작될 경우, 컴파일러가 이를 파악하고 물리주소를 정해놓는다. 단 이는 i번지가 변경되면 재컴파일을 해야하므로 이식성이 매우 떨어진다.
- 적재시점 바인딩 : 프로그램이 메인메모리에 적재될 때 프로그램의 시작시점 물리주소가 확정되면 코드 내 논리주소를 물리주소로 바꿔서 적재하는 방법이다. 시작주소가 변경되면 다시 로딩하면 되지만, 실행시점 바인딩보다는 유연성이 떨어진다.
- 실행시점 바인딩 : 먼저 논리주소인 채로 적재해놓고, 실행 중 MMU를 통해 물리주소를 결정하는 방법이다. 이 경우 DLL(dynamic Linking Library)이나 리눅스의 Shared Object와 같이 프로그램 실행 중 일부를 필요시 뒤늦게 로딩하는 경우나, 프로그램 전체를 재배치하는 등의 유연성을 실현할 수 있다. 차후 배우게 될 페이징, 가상메모리 기법도 이러한 실행시점 결속을 바탕으로 발전된 기법이다.
- 위에서 보았듯, 주소결속시점이 늦을 수록 메모리 경영의 유연성은 높아진다.
결속방식에 따른 메모리 경영 기법 분류
분류 | 공간크기 | 사상단위 | 적재단위 | 장단점 |
분할 | 논리 = 물리 | 전체 프로그램 | 전체 프로그램 | 단점 : 외부 단편화 |
페이지 | 논리 = 물리 | 페이지 (OR 가변크기) | 전체 프로그램 | 단점 : 페이지 테이블 |
가상 메모리 | 논리 > 물리 | 페이지 | 프로그램 일부 | 장점 : 오버레이가능 / 메모리 활용도 증대 |
- 앞으로 학습할 내용의 간단한 정리이다. 지금은 이해가 안가도, 다 학습하고 나면 이해가 가능해진다.
- 공간 크기의 차이와 사상 함수의 취급 단위, 적재 단위로 구분된다.
반응형
'💻 CS > 운영체제' 카테고리의 다른 글
[운영체제] 페이징 (0) | 2020.05.16 |
---|---|
[운영체제] 분할 (0) | 2020.05.16 |
[운영체제] 교착상태 처리 (0) | 2020.05.12 |
[운영체제] 교착상태 (0) | 2020.05.08 |
[운영체제] 세마포어 (0) | 2020.05.06 |