[운영체제] 18. Memory Management 1

이건회·2022년 3월 21일
0

운영체제

목록 보기
17/27
post-thumbnail

  • 메모리는 주소를 통해 접근할 수 있다. 이 주소는 논리적 주소와 물리적 주소로 나뉜다.
  • 이미 프로그램이 실행되면 독자적인 주소공간이 형성되는데, 프로그램마다 가지는 독립적 주소 공간을 논리적 주소라 한다.
  • 물리적 주소는 메모리에 실제 올라가는 위치를 나타낸다.
  • 프로그램이 물리적인 메모리에 어느 곳으로 올라갈지 결정하는 것을 주소 바인딩이라 한다.
  • Symbolic Address는 프로그래머 입장에서 숫자가 아닌 symbol로 된 주소를 사용하는 것이다. 이것이 컴파일 되어 숫자 주소로 바뀐다.

  • 주소 변환이 언제 이루어 지는가?
  • 먼저 컴파일 시간에 이루어지면 컴파일 타임 바인딩, 실행이 시작될 때 이루어지면 로드 타임 바인딩, 프로그램 시작 이후에도 실행 중간에 물리적 메모리 주소가 바뀔 수 있는 것을 익스큐션 타임 바인딩(런타임 바인딩)이라 한다.
  • 컴파일 바인딩에 의해 만들어진 실행파일 코드를 절대 코드라 부른다.
  • 로드 타임 바인딩을 하기 위해 만들어진 코드는 재배치 가능 코드다.

  • 맨 왼쪽에 소스코드가 있고 이는 심볼릭 어드레스로 주소가 표현되어 있다. 이게 컴파일되어 실행파일이 되면 심볼릭 어드레스가 숫자로 바뀌어 논리적 주소가 된다. 이것이 실행 되려면 물리적 메모리에 올라가야 하는데 물리적 메모리의 어디에 올라갈지 결정하는 것이 주소 바인딩이다.
  • 컴파일 타임 바인딩은 소스코드에서 실행파일로 컴파일될때 물리적인 주소가 이미 결정된 것이다. 이 방법을 쓰면 항상 이미 결정된 주소로만 올려야 한다. 따라서 빈 공간이 있어도 결정된 주소로 올려야 하므로 비효율적이다.
  • 로드 타임 바인딩은 프로그램이 시작되어 메모리에 올라갈 때 물리적 메모리 주소가 결정되는 것이다.
  • 런타임 바인딩은 실행 시 주소가 결정되는 것은 같지만 주소가 실행 중에 바뀔 수 있다. 아래 실행되는 도중에 주소가 300번지에서 700번지로 이동하는 것을 볼 수 있다.
  • CPU가 바라보는 주소는 논리적 주소다. 실행파일이 물리적 주소로 올라가도 코드가 바뀌지 않기 때문이다.

  • 논리적 주소를 물리적 주소로 바꾸는 주소변환용 하드웨어 지원이 필요하다. 이 하드웨어를 MMU라고 부른다. (Memory Management Unit)
  • 주소변환을 할 때는 기본적인 MMU에서는 레지스터 두 개를 활용해 주소변환을 한다.
  • 사용자 프로그램은 논리적 주소만을 다룬다. 물리적 주소는 실제로는 볼 수 없으며 알 필요도 없다.

  • CPU가 메모리 346의 내용을 달라고 하면 주소변환이 일어난다. 중간의 MMU에 있는 limit register와 relocation register를 활용해 주소를 변환한다.
  • 왼쪽 아래는 프로세스 p1의 논리적 메모리 주소를 나타내고 있다. 즉 현재는 프로세스의 0부터 3000까지의 메모리중 0부터 346까지를 cpu가 요청한 상황이다.
  • 현재 이 메모리는 물리적 주소의 14000부터 올라간 상황이다. 그러면 논리 주소와 시작 위치를 더해주면 된다. 따라서 14346을 찾아 cpu에 가져다주면 된다. relocation register에 시작 위치를 적어 놓으면 논리 주소에 시작 위치를 더해 물리적 주소를 찾을 수 있다.
  • limit register는 프로그램의 최대 크기를 적어 놓는다. p1은 3000의 크기라는 뜻이다. 만약 프로그램의 크기가 3000인데도 불구하고 악의적인 프로그램이 4000번지를 달라고 요청할 수 있다. 이러면 다른 프로그램의 메모리 위치를 요청할 수 있으므로 limit register에 적힌 수보다 높은 수의 요청을 하면, 주소를 주지 않는다.

  • 따라서 cpu가 요청을 하면 limit register값을 벗어나는 요청인지 검사를 한다. limit register 값을 벗어나면 트랩(소프트웨어 인터럽트)를 걸어 운영체제에게 cpu를 넘기고, 운영체제가 프로그램을 강제로 종료시키는 등의 응징을 한다.

  • 다이나믹 로딩은 프로그램을 메모리에 동적으로 올린다는 뜻, 즉 그때그때 해당 루틴이 불려질 때(필요할 때)마다 메모리에 프로그램을 올리는 것이다. 프로그램이 시작될 때 전체를 통째로 메모리에 올리지 않는다.
  • 일반적으로 사용되지 않고 가끔씩 사용되는 프로그램일 경우 유용하다.
  • 다이나믹 로딩의 개념은 운영체제의 직접적인 지원관리 없이, 프로그래머가 직접 다이나믹 로딩을 하는 개념이다. 운영체제는 프로그래머가 관리를 쉽게 하도록 라이브러리를 지원해줄 뿐이다.

  • 오버레이는 다이나믹 로딩과 비슷하게 메모리에 필요한 부분만 그때그때 올려 놓는다.
  • 그러나 모든 코드를 운영체제 라이브러리 없이 프로그래머가 수작업으로 해야 한다는 점에서 다이나믹 로딩보다 복잡하다.

  • 스와핑은 프로세스를 메모리에서 하드디스크에 있는 백킹 스토어(=스왑 에리어)로 쫓아내는 것이다.
  • 중기 스케줄러에 의해 스왑아웃 시킬 프로세스를 선정한다.

  • 메모리에서 쫓겨나 백킹 스토어로 내려가는 것을 스왑 아웃이라 하고, 백킹 스토어에서 메모리로 다시 올라오는 것을 스왑 인이라고 부른다.
  • 중기 스케줄러에 의해 스왑아웃 시킬 프로세스를 선정한다.
  • cpu 수행가능성이 낮은 프로세스 순서대로 스왑 아웃을 시킨다.
  • 스와핑이 효율적으로 사용되려면 런타임 바인딩이 지원되어야 한다.
  • 많은 양을 올리고 내려야 하므로 스왑 타임은 대부분 transfer time, 즉 데이터가 전송되는 시간에 비례한다.

  • 프로그램을 작성한 후 컴파일하고 "링크"라는 곳에서 실행파일을 만든다. 컴파일된 파일을 묶어 하나의 실행파일을 만드는 과정을 "링킹"이라 부르는데, 누군가가 만들어 놓은 라이브러리가 내 프로그램의 실행파일 코드에 포함되는 개념이 스태틱 링킹이다.
  • 반면 라이브러리 코드가 내 실행 파일 안에 포함되지 않고 남아 있다가, 프로그램을 실행을 한 후 프로그램이 라이브러리를 호출하는 곳에 도달하면 내 코드 안에 라이브러리 코드가 없으므로, 라이브러리 코드를 찾아야 한다. 따라서 라이브러리의 위치를 찾을 수 있는 stub이라는 작은 코드를 실행 파일에 포함시켜 놓고, 라이브러리 호출 시 이를 통해 찾는 방법이 다이나믹 링킹이다. 라이브러리가 메모리에 없으면 포함시키고, 이미 메모리에 있으면 그 루틴의 주소로 가서 라이브러리를 실행 시킨다.
  • 다이나믹 링킹을 해주는 라이브러리를 shared library라 한다.

  • 물리적인 메모리를 어떻게 관리할까. 오른쪽 박스가 물리적 메모리의 예시다. 낮은 주소 부분에 운영체제 커널이 있고, 높은 주소 영역에는 사용자 프로세스가 올라가 있다. 사용자 프로세스를 관리하는 방법은 연속 할당과 불연속 할당이 있다.
  • 프로그램이 메모리에 올라갈 때 통째로 올라가는 방법이 연속 할당이다.
  • 반면 불연속 할당은 프로그램을 구성하는 주소공간을 잘게 쪼개서 하나의 프로세스가 메모리의 여러 영역에 분산되어 올라가는 방법이다.

  • 연속 할당도 고정 분할 방식과 가변 분할 방식으로 나눌 수 있다.

  • 고정 분할 방식은 사용자 프로그램이 들어갈 물리적인 영역을 미리 파티션으로 나누어 놓는 것이고, 가변 분할 방식은 이 영역을 미리 나누지 않는 것이다.
  • 고정 분할 방식에서는 프로그램 A를 분할 1에 올린다. 프로그램 B를 올리려는데 분할 2보다 프로그램이 크므로 분할 3에 B가 들어간다. 그러나 분할 3이 B보다 크므로 낭비 공간이 발생한다.
  • 이 낭비공간을 외부 조각과 내부 조각이라 하는데, 외부 조각은 프로그램 크기보다 분할의 크기가 작은 경우(분할 2)이고, 내부 조각은 프로그램 크기보다 분할의 크기가 큰 경우(분할 3)이다.
  • 가변 분할 방식은 프로그램이 실행될 때 마다 프로그램을 메모리에 차곡차곡 올린다. 실행하던 중 만약 프로그램 B가 끝나면 빈 공간이 발생하고 프로그램 D가 실행되는데, D가 B가 점유하던 공간보다 크므로 빈 공간에 들어가지 못하고 아래 쪽으로 들어가게 된다. 따라서 위의 빈 공간이 외부 조각, 아래 공간이 내부 조각이 된다.

  • 가변 분할 방식을 사용하면 빈 공간, 가용 메모리 공간인 hole이 생기는데 프로세스가 도착하면 운영체제는 수용가능한 hole을 할당한다. 따라서 운영체제는 할당 공간과 가용 공간의 정보를 유지한다.

  • 홀 중에서 어느 홀에 새로운 프로그램을 집어넣을 것인지에 대한 문제를 다이나믹 스토리지 얼로케이션 문제라 부른다. 적어도 프로그램의 크기 n보다 큰 곳을 찾아야 할 것이다.
  • 세 가지 방법이 있다. 퍼스트 핏 방법은 n보다 큰 홀중 가장 먼저 발견되는 홀에 넣는 것이다.
  • 베스트 핏은 전체 홀 중 맞는 홀을 전부 살피고 가장 작은 홀에 프로그램을 넣는 것이다.
  • 워스트 핏은 가장 큰 홀에 할당하는 방법이다. 이는 낭비가 많아 상대적으로 아주 큰 홀이 생성된다.
  • 퍼스트 핏과 베스트 핏이 워스트핏 보다 속도 혹은 공간 이용률 측면에서 효과적이다.

  • 홀을 전부 한 곳으로 몰아 아주 큰 홀을 만들어 프로그램이 들어갈 공간을 만드는 것을 컴팩션이라 한다.
  • 이는 매우 비용이 많이 든다. 전체 프로그램의 바인딩과 관련되어있기 때문이다.
  • 최소한의 프로그램만을 이용시켜 큰 홀을 만들도록 하는 것이 중요하다. 이 역시 매우 복잡하다.

  • 지금까지는 연속 할당을 이야기했고, 이제부터는 불연속 할당을 이야기하도록 하겠다.
  • 불연속 할당은 프로그램을 구성하는 주소 공간을 같은 크기의 페이지로 자르는 것이 페이징 기법이다. 물리적 주소 공간을 페이지에 맞게 자르는데 이 공간을 페이지 프레임이라 한다. 이를 사용하면 홀의 크기가 균일하지 않은 문제가 생기지 않는다. 이 경우 주소 변환이 복잡하다. 주소변환을 페이지 별로 해야 하기 때문이다.
  • 다음인 세그멘테이션 기법은 프로그램의 주소 공간을 의미 있는 단위로 자르는 것이다. 프로그램 주소 공간은 코드 데이터 스택으로 구성되는데, 세그멘테이션 기법은 코드 세그먼트, 데이터 세그먼트, 스택 세그먼트로 잘라 각각의 세그먼트를 필요시 물리적 메모리의 다른 위치로 올리는 방법이다. 각각의 함수 또한 세그먼트 단위로 잘라 물리적 메모리로 올릴 수 있다. 따라서 크기가 균일하지 않고 홀이 발생하여 다이나믹 스토리지 얼로케이션 문제가 생기게 된다.
profile
하마드

0개의 댓글