초기 시스템
초기 컴퓨터는 하나의 메모리에 단 하나의 프로세스만 올릴 수 있었다.
위의 그림과 같이 물리 메모리에 하나의 실행 중인 프로세스가 존재하였으며 OS를 제외한 나머지 메모리를 사용했다.
하지만 하나의 프로세스만 실행할 수 있고 메모리 공간을 다 차지하기 때문에 매우 안 좋은 활용성과 효율성을 보여줬다.
시간이 흘러 멀티 프로그래밍을 지원하게 되면서 사람들은 컴퓨터를 더 효율적으로 사용하게 되었다.
멀티 프로그래밍과 시분할
앞서 설명했던 초기 시스템의 문제를 해결하기 위해 시분할(Time Sharing) 기법을 사용하여 여러 개의 프로그램을 하나의 메모리에서 실행할 수 있도록 멀티 프로그래밍을 할 수 있게 메모리 구성이 바뀌었다.
하나의 메모리에 여러 개의 프로세스를 올려 실행하게 되면서 메모리의 활용성과 효율성이 증가할 수 있었다.
하지만 메모리의 활용성과 효율성이 증가했지만 여러 프로세스들이 한 메모리에 존재하게 되므로 프로세스 간에 서로 데이터를 침범할 수 있다.
예를 들면 위의 그림과 같이 메모리에 프로세스가 올려져 있는데 여러 개의 프로세스들이 한 번에 메모리에 접근하게 되면 기존에 실행 중인 프로세스에 접근할 수 있게 되면서 보안상 문제가 발생할 수 있다.
이러한 문제점을 해결하기 위해 프로세스를 메모리에 그대로 유지하면서 운영 체제가 시분할을 효율적으로 구현할 수 있게 하는 것이 가상 메모리의 목표이다.
주소 공간(Address Space)
프로그램이 실행되면 운영 체제는 실행 파일의 명령들을 읽어 프로세스를 생성하고 메모리를 할당하게 되는데 이를 프로세스 주소 공간이라고 한다.
주소 공간은 현재 실행 중인 프로그램, 즉 프로세스의 모든 정보가 들어있다. 즉, 코드, 스택, 힙과 같이 프로그램을 실행시키기 위한 모든 상태를 주소공간이 가지고 있게 된다.
주소 공간의 구성
- 스택 영역
- 함수 호출과 관련된 지역 변수, 매개변수 등이 저장되는 공간
- 함수가 호출될 때 할당하고, 함수가 종료되면 해제
- 메모리의 상위 주소에서 하위 주소 방향으로 할당
- 힙 영역
- 프로그램 실행 중에 크기가 결졍되는 동적 메모리 영역
- 사용자가 직접 공간을 할당하고 해제가 가능
- 참조형 데이터(객체)가 저장
- 메모리의 하위 주소에서 상위 주소 방향으로 할당
- BSS 영역
- 초기화되지 않은 전역 변수와 정적 변수가 저장되는 메모리 영역
- BSS 영역의 변수들은 프로그램 시작 시 자동으로 0이나 NULL로 초기화
- 데이터 영역
- 전역 변수나 정적(static) 변수 등 프로그램에서 사용하는 데이터가 저장되는 영역
- 전역/정적 변수를 참조하는 코드가 있다면 컴파일 후 데이터 영역을 참조
- 프로그램을 시작할 때 할당되고 종료되면 해제
- 텍스트 or 코드 영역
- CPU가 실행할 수 있는 기계어 코드가 저장된 영역
- 프로그램 코드는 변경되면 안 되므로 읽기 전용으로 보호
그림을 보면 프로그램 코드가 메모리 하위 주소에 배치되는데, 프로그램 코드는 정적이기 때문에 프로그램이 실행되면서 추가적으로 메모리를 필요로 하지 않게 되면서 메모리에 저장하기 쉽기 때문에 하위 주소에 배치한다.
그다음으로 오는 Heap과 Stack 영역은 동적으로 할당되기 때문에 중간의 free 공간을 두어서 배치하게 된다.
가상 메모리(Virtual Memory)
가상 메모리는 운영 체제가 실제 메모리를 추상화해서 현재 실행 중인 프로그램에게 나눠 주는 것을 의미한다.
가상 메모리의 핵심은 운영 체제가 프로세스에게 특정 주소의 메모리에 올라가고 잠재적으로 매우 큰 주소 공간을 가지고 있다고 착각하게 만다는 것이다.
착각하게 만든다는 것이 조금 어렵게 느껴질 수 있는데, 예를 들면 어떤 게임의 용량이 20GB이고 내가 사용하는 PC의 물리 메모리가 16GB라고 가정해 보자.
게임을 실행하면 물리 메모리보다 용량이 크기 때문에 실행할 수 없을 것 같지만 잘 실행되는 것을 알 수 있다. 이렇게 큰 용량이 많은 메모리를 사용하는 것처럼 착각하게 만들어 준다는 뜻이다.
가상 메모리에서는 프로세스마다 각자의 메모리를 갖게 된다. 즉, 프로세스의 가상 메모리의 주소가 같다고 해서 물리적인 메모리의 주소가 절대 같지 않다.
예를 들어 P1, P2, P3이 가지고 있는 가상 메모리의 주소에서 똑같은 100이라는 물리 메모리를 가리킨다고 해도 물리 메모리에서는 서로 다른 메모리 주소로 변환된다.
또한 프로세스가 만약 2GB의 메모리를 사용한다고 해서 실제 물리 메모리가 2GB를 사용하는 것이 아니다.
어떻게 2GB의 가상 메모리를 사용하는데 실제 물리 메모리는 그만큼 사용하지 않는 것일까?
그것은 바로 필요한 부분만 메모리에 적재하기 때문이다.
프로세스를 실행할 때, 실행에 필요한 부분만 메모리에 올리기 때문에 실제 메모리 보다 큰 프로그램도 실행할 수 있게 되는 것이 가상 메모리의 특징이다.
가상 메모리의 목표
- 투명성
- 프로세스는 마치 자신만의 독립된 메모리 공간을 가진 것처럼 인식하여 실제 물리 메모리의 복잡성은 운영 체제에 의해 추상화돼야 한다.
- 효율성
- 운영 체제는 가상화를 시간과 공간 측면에서 효율적 이도록 진행해야 한다.
- 운영 체제가 가상 주소를 실제 물리 주소로 변환하는 과정에서 발생하는 오버헤드를 최소화해야 한다.
- 이러한 효율을 위해 페이지 테이블이나 TLB와 같은 하드웨어 지원을 받아야 한다.
- 보호
- 운영 체제는 프로세스를 다른 프로세스로부터 보호해야 하고 운영 체제 자신도 다른 프로세스로부터 보호해야 한다.
- 프로세스는 오직 자신의 가상 주소 공간 내에서만 메모리에 접근할 수 있어야 하며 다른 프로세스의 메모리 영역에는 절대 접근할 수 없어야 한다.
- 이러한 보호 기능을 활용하여 프로세스를 서로 격리시켜 특정 프로세스에서 발생한 문제가 다른 프로세스에 영향이 가지 않도록 해야 한다.
참고 자료
'CS > OS' 카테고리의 다른 글
운영체제 - 페이징과 세그먼테이션 (0) | 2024.07.02 |
---|---|
운영체제 - 주소 변환 (0) | 2024.06.30 |
운영체제 - PCB와 Context Switching (0) | 2024.06.27 |
운영체제 - 시스템 콜 (0) | 2024.06.26 |
운영체제 - 인터럽트(Interrupt) (0) | 2024.06.25 |