
메모리
주소를 통해 접근하는 장치
메모리 주소 2종류

- 물리적 메모리
- 물리적 주소 0번지부터 시작
- 낮은 주소는 운영체제 높은 주소는 여러 프로세스들
- 사용자 프로그램은 디스크 실행파일에서 메모리에 올라가서 프로세스가 되는 것
- 여기서 한 단계를 더 거치는데
프로그램만의 독자적 메모리 주소 공간(논리적 주소 또는 가상 주소)을 거친다

- 프로그래머는 숫자로된 주소가 아니라 심볼로 된 주소를 가지고 프로그래밍한다
심볼링 어드레스가 컴파일되면 독자적 메모리주소가 매겨지고,
메모리에 올라가서 실행이 되면 물리적 메모리 주소를 가지게 된다
- 이 과정에서 주소 변환이 이루어진다
주소 바인딩

논리적 주소를 물리적 주소로 맵핑하는 과정
이 시점이 언제일까?

MMU

주소 변환 하는 하드웨어
간단한 주소 변환 방식은 아래와 같이 이루어진다

*프로그램에 논리적 주소가 있고, 물리적 메모리로 올라갈 때 묶여서 올라가는 상황을 전제로 설명한다

CPU가 로지컬 어드레스를 줄 때,
먼저 MMU는 그 레지스터가 리밋보다 작은지 체크한다
만족하면 주소를 변환히고
아니라면 트랩을 발생시킨다
- 트랩
- 소프트웨어어 인터럽트 > 다음 인스트럭션 실행하기 전에 cpu가 운영체제로 넘어간다
- 운영체제는 악의적 메모리 접근하는 프로그램을 종료시키고,
정상이라면 시작위치에 더해서 메모리에 접근한다

다이나믹 로딩

- 프로그램을 구성하는 프로세스 주소 공간이 불릴 때 메모리에 그때그때 동적으로 올리는 것
- 장점은 메모리 유틸라이제이션이 좋아진다는 것
프로그램 안에 예외적 상황을 처리하는 코드들이 많은데 이런것까지 올려놓으면 메모리 낭비가 된다
당장 필요한 실행되는 부분만 올려놓아서 사용률이 좋아진다
- 다이나믹 로딩은 운영체제 특별한 지원 없이 프로그램 자체에서 구현 가능
현대적 OS에서 하는 방식은 엄밀히 다이나믹 로딩 아니다 > 운영체제 지원 없이 프로그램 자체에서 라이브러리 통해 구현
오리지널 다이나믹 로딩은 운영체제 지원 없이 라이브러리 통해 하는 것을 원래 의미했었다
오버레이
- 실제 필요한 부분만 그때그때 메모리에 올린다는 의미
(다이나믹 로딩과 의미가 같다)
- 초창기에는 물리적 메모리 크기가 작아서 프로그래머가 수작업으로 메모리에 올리고 내리고를 프로그래밍 하는 것 > 오버레이
스와핑
- 프로그램을 메모리에서 통째로 쫓아내는 것
- 어디로? 디스크 스토리지

- 왼쪽이 물리적 메모리 오른쪽이 backing 스토리지
워드 프로세서라는 프로그램이 메모리에 있다가 스왑아웃이 되면 통째로 쫓겨난다
웹브라우저라는 프로그램이 쫓겨나있다가 스왑인이 되면 물리적 메모리에 다시 올라간다
- 스와핑에서 사용되는 쫓겨나는 영역은 swap area(backing store)
중기 스케줄러(메모리에 너무많은 프로그램이 동시에 올라가잇으면 비효율적이라 일부 프로세스를 통째로 쫓아내는 것, 쫓겨나는 경우에 상태는 서스펜디드)에서 스왑아웃 된다면 서스펜디드
스완인되면 레디나 블럭과 같은 액티브한 상태로 올라간다
어떤 프로세스를 쫓아내는가?
CPU 우선순위가 낮은 프로세스
CPU에서 실행될 가능성이 낮은 것을 최우선 타겟으로 쫓아낸다
- 바인딩
- 컴파일이나 로드타임 바인딩에서는 스와핑이 지원되는데 제한 사항이 있다
- 스왑아웃시키면 그 부분은 비어있게 된다
다시 메모리에 올리고싶을 때, 다른 메모리 부분이 비어있어도 500에 올려야 한다 (주소가 바뀌면 안됨)
원래 메모리 위치 고집하는 것 > 비효율적
- 스와핑이 빈 메모리 공간을 잘 사용할려면 런타임 바인딩이 지원되어야 한다
런타임 바인딩에서는 300에서 스왑아웃 되었다가 이후 메모리에 여유가 생겨서 700번지가 생기면 거기에 올려도 된다 > 빈 메모리 어디든지 효율적으로 사용

위에서 B가 스왑아웃된 상황?
- 오리지널 스와핑에서 스왑아웃은 통째로 쫓겨날 때 스왑아웃 된 것
- B는 조각 중 2개는 물리적 메모리에 있고 하나만 쫓겨난 상황
- 일부 페이지만 쫓겨난 것이기 때문에 현대적 운영체제에서는 한 페이지만 스왑아웃 됐다고 말하기도 한다
다이나믹 링킹

프로그램 하나를 만들면 컴파일 되고 링킹이 되어서 실행파일이 만들어진다
링킹은 실행하기 이전에 작성한 프로그램이 사용하는 다른 프로그램이나 라이브러리를 가져와 연결하는 과정
링킹이 언제되는가?
-
스태틱 링킹
- 내가 만든 코드 + 라이브러리
- 내가 만들지 않은 라이브러리가 컴파일 하고 나면 내 코드 안에 포함되는 것
-
다이나믹 링킹
- 라이브러리가 내 실행파일에 존재하지 않고 별도 파일 형태로 존재
- 필요할 때 라이브러리를 파일 형태로 찾아서 메모리에 올리고 연결해서 실행시키는 것
- 라이브러리 위치정보만 포함되어 있음
* 리눅스 환경에서는 쉐어드 오브젝트가 .so로 끝난다
윈도우즈 환경에서는 .dll
-
특징
- 스태틱은 함수를 프로그램에 각각 사용해서 컴파일 하면 각각의 프로그램 안에 들어가있다
각 주소공간에 함수가 개별적으로 다 들어가 있다
- 다이나믹 링킹 쉐어드 라이브러리로 구현되어있으면 실행파일 안에 없고 어떤 파일에서 찾을 수 있다고만 적혀져 있다
- 불리는 순간 쉐어드 라이브러리를 메모리에 올려서 실행
- 다른 프로그램이 호출하는 순간 중복해서 메모리에 올리는게 아니라 이미 올라간 쉐어드 라이브러리를 공유해서 쓴다
물리적 메모리 관리 기법
오른쪽 그림이 물리적 메모리
낮은 주소영역에는 운영체제 커널이 상주
나머지 영역에는 사용자 프로그램이 올라간다
사용자 프로그램이 올라간 주소 영역 어떻게 관리할까?
-
연속할당
- 프로그램이 쪼개지지 않고 통째로 올라가는 것
- 주소변환이 간단하다
시작위치만 알면 얼만큼 떨어져있는지만 더해준다
-
불연속할당
- 프로세스 주소공간이 잘려서 산발적으로 올라가거나 쫓겨날 수 있음
연속 할당


- 고정분할
- 물리적 메모리를 4개의 파티션으로 미리 나눔
각각 파티션에는 프로그램 하나씩 들어감
프로그램 A가 분할1에 들어갈 크기 > 들어가서 실행
프로그램 B는 분할 2에 작아서 못들어가고 3에 들어감
- 분할3에서 남는 공간 생김 > 내부 조각
낭비되는 조각이 생겨서 비효율적
- 분할 2도 크기가 안맞아서 활용이 안됨 > 외부 조각
- 가변분할
- 미리 나누지 않고 차례로 실행되면 낭비되는 공간 없이 쓸 수 있다
- B가 종료되면 비어서 다른 프로그램이 올라갈 수 있다
- D 크기가 외부조각보다 더 크면 뒤에다 넣음 (크기가 안맞음) > 외부조각
- 내부조각이 생기지는 않는다
개념적으로 못들어가는거지 나중에 맞는 프로그램이 들어가면 낭비 공간은 아니기 때문에 개념적으로만 보기

홀
- 홀 조각들은 다 가용메모리 공간
프로그램 실행되고 종료되고 그러다 보면 홀이 여러군데 작게 생길 수 있다
- 운영체제는 사용중 공간과 가용공간을 유지해야 한다
어느 홀에 올릴 것인가?

1. 퍼스트핏
빈 공간 중 발견되는 제일 첫번째 공간에 올리는 것
-
베스트 핏
여러 홀 중 가장 적합한 곳
장점은 큰 공간은 유지하고 맞춤형 할당
단점은 탐색
-
워스트 핏
제일 큰 홀에 집어넣는 것
큰 홀은 더 큰 프로그램을 위해 쓸 수도 있기 때문에 부적절한 측면이 있다
퍼스트와 베스트가 워스트보다 더 효율적

- 컴팩션
- 홀을 모아서 쓰는 방법
- 고비용
- 메모리를 이동시키기 때문에 비효율적
- 이론적으로 복잡하다
- 실행중 프로그램 물리적 주소가 동적으로 바뀌므로 바인딩 중에서 런타임 바인딩에서만 컴팩션이 가능