1 minute read

시분할 시스템이 대중화되면서 
여러 프로그램이 메모리에 동시에 존재하게 되었다.
어떤 프로세스가 다른 프로세스의 메모리를 
함부로 읽거나 수정하는 일은 없어야 한다.

주소 공간(address-space)

  • 과거에는 시분할을 구현하기 위해 하나의 프로세스를 굉장히 짧은 시간 실행시키고, 그 시간동안 프로세스는 모든 메모리에 접근이 가능해서 현재 프로세스를 종료시키고 새로운 프로세스를 실행시키는 것을 반복한다. 이는 메모리가 커질수록 매우 느려지게 된다.
  • 프로세스 전환 시 프로세스를 메모리에 그대로 유지하면서, 시분할 시스템을 효율적으로 작동하기 위해 주소 공간이라는 개념이 필요하게 되었다.

Screen Shot 2023-01-06 at 2 45 38 PM

  • 주소 공간은 실행 프로그램의 모든 메모리 상태를 갖고 있다. 프로그램의 코드(code, 명령어)는 반드시 메모리에 존재해야 한다. 스택은 함수 호출 체인 상의 현재 위치, 지역 변수, 함수 인자와 반환 값 등을 저장하는 데 사용된다. 마지막으로 힙(heap)은 동적으로 할당하는 메모리를 위해 사용된다.
  • 스택과 힙 메모리 영역은 확장할 수 있어야 하기 때문에 양 끝으로 배치한다. (스택과 힙의 메모리 위치는 구현에 따라 달라질 수 있다)

가상화의 목표

1. 투명성(transparency)

  • 운영체제는 실행 중인 프로그램이 가상 메모리의 존재를 인지하지 못하도록 가상 메모리 시스템을 구현해야 한다. 즉, 프로그램은 전용 물리 메모리를 소유한 것처럼 행동해야 한다.

2. 효율성(efficiency)

  • 가상화는 시간, 공간효율적이어야 한다. 즉, 너무 느리게 실행되거나 너무 많은 메모리를 사용해서는 안된다.

3. 보호(protection)

  • 운영체제는 프로세스를 다른 프로세스로부터 보호해야 하고 운영체제 자신도 보호해야 한다. 즉, 어떤 명령어를 실행할 때 다른 프로세스나 운영체제의 메모리 내용에 접근하거나 영향을 주어서는 안된다.

고립의 원칙

  • 한 프로세스가 다른 프로세스에게 피해를 주는 것을 방지하며, 프로세스가 운영체제의 동작에 영향을 줄 수 없다는 것을 의미한다. 이는 신뢰할 수 있는 시스템을 구축하는데 중요한 원칙이다.

사용자가 보는 주소

  • 사용자가 보는 주소는 가상 주소(virtual address)이다. 물리 메모리 주소를 알 수 있는 것은 오직 운영체제뿐이다.
  • 어떤 간단한 프로그램에서 main(code), malloc(heap), 지역변수(stack)의 주소를 출력해보면 code영역 > heap영역 > stack영역(반대편에서 증가)에 메모리가 위치한다는 것을 알 수 있다.
#include <stdlib.h>
#include <stdio.h>

int g_data = 0;

int main(void)
{
	int hello = 3;
	printf("code, main:%p\n", (void *)main);
	printf("data, g_data:%p\n", (void *)&g_data);
	printf("stack, hello:%p\n", (void *)&hello);
	printf("heap, malloc:%p\n", (void *)malloc(sizeof(int) * 5));
}
  • 출력
code, main:0x1008d7ec0
data, g_data:0x1008dc000
stack, hello:0x16f52b5cc
heap, malloc:0x600000a15120
  • m1 mac에서는 code > stack > heap순으로 메모리가 위치한다는 걸 알 수 있다.