[운영체제] Chapter 8. Memory Management (1)
2023. 1. 16. 19:11ㆍCS/운영체제
728x90
//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎
Logical vs Physical Address, 주소바인딩(Address Binding), Memory-Management Unit(MMU), Dynamic Relocation, Hardware Support for Address Translation, Some Treminologies, Dynamic Loading, Overlays, Swapping, Dynamic Linking, Allocation of Physical Memory, Contiguous Allocation
1. 논리적(Logical) 주소와 물리적(Physical) 주소
- 메모리: 주소를 통해 접근하는 저장장치
- 주소 - 논리적 주소, 물리적 주소
- 논리적 주소(logical address, 가상주소(virtual address))
- 프로그램이 실행을 위해 메모리에 적재되면 그 프로세스를 위해 생성되는 독자적인 주소 공간
- 각 프로세스마다 할당되며 0번지부터 시작한다.
- CPU가 보는 주소는 논리적 주소이다.
- 논리적 주소와 물리적 주소에 있는 instruction 안에 있는 코드는 바뀌지 않기 때문
- CPU는 메모리 접근을 할 때마다 주소 변환을 해서 메모리에 접근해야 한다.
- 물리적 주소(physical address)
- 물리적 메모리에 실제로 올라가는 위치
- 물리적 메모리의 낮은 주소 영역에는 운영체제가, 높은 주소 영역에는 사용자 프로세스들이 올라간다.
- 물리적 주소는 하나로, 0 번지부터 통으로 관리한다.
- 물리적 메모리에 실제로 올라가는 위치
- 프로세스가 실행되기 위해서는 해당 프로그램이 물리적 메모리에 올라가 있어야 하고, CPU가 기계어 명령을 수행하기 위해 논리적 주소를 통해 메모리 참조를 하게 되면 해당 논리적 주소가 물리적 메모리의 어느 위치에 매핑되는지 확인해야 한다.
⇒ 주소 바인딩(address binding)
2. 주소 바인딩(address binding)
- 프로세스의 논리적 주소를 물리적 메모리 주소로 연결시켜 주는 작업
- Symbolic Address → Logical Address(프로그램만의 독자적인 주소) → Physical Address(메모리에 올라가서 실행)
- Symbolic Address: 프로그래머가 숫자 주소로 프로그래밍하지 않음, 프로그래머가 바라보는 주소
- 변수 저장 - 메모리 몇 번지에 저장 명령 X
- 함수 호출 - 메모리 몇 번지로 jump 명령 X
- 숫자로 된 주소를 사용하지 않고, symbol로 된 주소(= 함수, 변수 이름과 같이)를 사용한다.
- Symbolic Address가 컴파일되면 숫자로 된 Logical Address로 변환된다.
- Logical Address가 실행이 되려면 물리적인 메모리에 올라가 Physical address로 변환이 되어야 하는데
(= 주소 바인딩) 이 시점이 언제인가? - 물리적 메모리의 주소가 결정되는 시기에 따라 세 가지로 분류
- Symbolic Address: 프로그래머가 숫자 주소로 프로그래밍하지 않음, 프로그래머가 바라보는 주소
2-1. Compile time binding
- 프로그램을 컴파일할 때 물리적 메모리 주소 결정
- 컴파일을 하는 시점에 해당 프로그램이 물리적 메모리의 몇 번지에 위치할 것인지를 결정해야 하기 때문에
- 논리적 주소가 물리적 주소이다. → 주소 변환이 필요 없다.
- 절대 코드(absolute code) 생성하는 바인딩 방식
- 항상 0 번지부터 시작하고, 컴파일할 때 미리 결정되기 때문에 비효율적이어서 현대의 컴퓨터 시스템에서는 사용하지 않는다.
예전 컴퓨터에서 하나의 프로그램만 실행되는 환경에서 주로 사용했다.- 또한 여러 프로그램이 멀티 태스킹 되는 현대의 운영체제는 0번지부터 올라감 → 컴파일 타임 바인딩은 적절하지 않음
- 프로그램이 올라가 있는 물리적 메모리의 위치를 변경하고 싶다면 재컴파일
2-2. Load time binding
- 프로그램의 실행이 시작될 때 물리적 메모리 주소 결정
- Loader의 책임하에 물리적 메모리 주소를 부여되며 프로그램이 종료될 때까지 물리적 메모리상의 위치가 고정
- Loader: 사용자 프로그램을 메모리에 적재시키는 프로그램
- 컴파일러가 재배치가능코드(relocatable code)를 생성한 경우에 가능한 주소 바인딩 방식
- 항상 특정 위치에 올라가야 되는 것이 아니라 실행 시 비어있는 위치 어디에나 올라갈 수 있는 코드
2-3. Execution time binding(= Run time binding)
- 프로그램이 실행을 시작한 후에도 그 프로그램이 위치한 물리적 메모리상의 주소가 변경될 수 있는 바인딩 방식
- CPU가 주소를 참조할 때마다 해당 데이터가 물리적 메모리의 어느 위치에 존재하는지, 주소 매핑 테이블(address mapping table)을 이용해 바인딩을 점검
- 하드웨어적인 지원이 필요하다.
- 기준 레지스터(base register), 한계 레지스터(limit register), MMU(Memory Management Unit: 메모리 관리 유닛 - 논리적 주소를 물리적 주소로 매핑해 주는 하드웨어 장치)
- 하드웨어적인 지원이 필요하다.
3. MMU(Memory Manangement Unit: 메모리 관리 유닛)
- MMU(Memory Management Unit): 논리적 주소를 물리적 주소로 매핑해 주는 하드웨어 장치
- MMU scheme(MMU 기법): CPU가 특정 프로세스의 논리적 주소를 참조하려고 할 때 그 주소값에 relocation register의 값을 더해 물리적 주소값을 얻어낸다.
- relocation register(재배치 레지스터, = base register(기준 레지스터)): 프로세스의 물리적 메모리 시작 주소
- MMU scheme에서는 프로그램의 주소 공간이 물리적 메모리의 한 장소에 연속적으로 적재되는 것을 가정하기 때문에 물리적 메모리상의 시작 주소만 알면 주소 변환을 쉽게 할 수 있다.
- limit register(한계 레지스터): 프로세스가 자신의 주소 공간을 넘어서 수행 중인 프로세스의 논리적 주소의 최댓값,
즉 그 프로세스의 크기를 담고 있다.- 프로세스가 자신의 주소 공간을 넘어서는 메모리 참조를 하려고 하는지 체크하는 용도로 사용
- CPU가 메모리 참조 요청을 했을 때 그 주소가 limit register 값 보다 큰지를 체크해
- 적다면 논리적 주소값에 relocation register 값을 더해 물리적 주소를 구한 다음 해당 물리적 메모리 위치에 접근하도록 허락하여 운영체제 및 다른 사용자 프로세스가 존재하는 물리적 메모리 영역에 대한 보안을 유지한다.
- 크다면 다른 프로세스의 주소 영역에 접근하려는 시도이므로 트랩을 발생시켜 해당 프로세스를 강제종료 시킨다.
- relocation register(재배치 레지스터, = base register(기준 레지스터)): 프로세스의 물리적 메모리 시작 주소
- 유저 프로그램은 logical address만을 다루기 때문에 실제 physical address를 볼 수 없으며 알 필요가 없다.
4. 메모리 관리와 관련된 용어
4-1. Dynamic Loading (동적 로딩)
- 프로세스 전체를 메모리에 미리 다 올리는 것(= 정적 로딩)이 아니라 실행에 필요한 부분이 실제로 불릴 때마다 메모리에 load(적재)하는 것
- 여러 프로그램이 동시에 메모리에 올라가서 수행되는 다중 프로그래밍 환경에서 메모리 사용의 효율성을 높이기 위해 사용
- memory utilization의 향상
- 프로그램의 코드 중 상당 부분은 오류 처리루틴과 같이 아주 특별한 경우에만 가끔씩 사용되는 방어용 코드인데, 이러한 코드 전체를 물리적 메모리에 올리는 경우 많은 메모리를 차지하게 되어 메모리 낭비 초래
- 동적 로딩 기법은 사용되지도 않을 많은 양의 코드가 메모리에 올라가는 것을 막아 메모리에 더 많은 프로그램을 적재할 수 있기 때문에 메모리를 좀 더 효율적으로 사용할 수 있다.
- 운영체제의 특별한 지원 없이 프로그램 자체에서 구현이 가능하며 운영체제가 라이브러리를 통해 지원할 수도 있다.
- OS가 관리하는 페이징 기법과는 다름
- 현대적인 운영체제에서도 메모리가 통째로 올라가는 것이 아니라 필요한 부분만 운영체제가 올리고 있음: dynamic loading이라고도 부를 수 있다.
4-2. Manual Overlays (중첩)
- 프로세스의 주소 공간을 분할해 실제 필요한 부분만을 메모리에 적재하는 기법
- Dynamic Loading과의 차이점
- Overlays는 하나의 프로세스조차도 메모리에 한꺼번에 올릴 수 없던 초창기 시스템에서 사용
- 프로세스의 주소 공간을 분할해서 당장 필요한 일부분을 메모리에 올려 실행하고 해당 부분에 대한 실행이 끝난 후에 나머지 부분을 올려 실행하는 기법
- 프로그램의 크기가 물리적 메모리의 크기에 비해 작다면 주소 공간 전체를 한꺼번에 올릴 수 있다.
- 동적 로딩) 메모리에 더 많은 프로세스를 동시에 올려놓고 실행하기 위한 용도
- 중첩) 단일 프로세스만을 메모리에 올려놓는 환경에서 메모리 용량보다 큰 프로세스를 실행하기 위한 용도
- 운영체제의 지원 없이 사용자에 의해 구현 - manual overlay: 수작업으로 한다
4-3. Swapping (스와핑)
- 메모리에 올라온 프로세스의 주소 공간 전체를 backing store로 쫓아내는 것, 프로세스가 종료되어 그 주소공간을 디스크로 내쫓는 것이 아니라 수행 중인 프로세스의 주소 공간을 일시적으로 메모리에서 디스크로 내려놓는 것을 의미
- backing store (= swap area): 디스크 내에 파일 시스템과는 별도로 존재하는 일정 영역
- 프로세스가 수행 중인 동안에만 디스크에 일시적으로 저장하는 공간
- 많은 사용자의 프로세스 이미지를 담을 만큼 충분히 빠르고 큰 저장 공간이어야 한다.
- swap out: 메모리 → 디스크로 내리는 작업
- 일반적으로 중기 스케줄러(swapper)에 의해 swap out 시킬 프로세스를 선정한다.
- degree of multiprogramming을 조절: 너무 많은 프로그램이 메모리에 동시에 올라오게 되면 프로세스당 할당되는 메모리의 양이 지나치게 적어져 시스템 전체의 성능이 크게 떨어진다.
- CPU 우선순위가 낮은 프로세스를 swap out 시키고(= suspend 상태), 우선순위가 높은 프로세스를 swap in
- 일반적으로 중기 스케줄러(swapper)에 의해 swap out 시킬 프로세스를 선정한다.
- swap in: 디스크 → 메모리로 올리는 작업
- compile time binding, load time binding에서는 원래 메모리 위치로 swap in 해야 하기 때문에 효율적으로 동작하지 않는다.
- execution time binding에서는 추후 빈 메모리 영역 아무 곳에나 올릴 수 있기 때문에 swap in에 적절하다.
- swap time은 대부분 transfer time이 대부분을 차지한다.
- transfer time: 데이터를 전송하는 시간
- seek time: 디스크를 접근하는 시간: 디스크 헤드가 이동하는 시간이 대부분을 차지하고 데이터를 전송하는 transfer time은 굉장히 미미한 규모를 차지
- 그렇지만 용량이 방대한 swapping 시스템에서는 seek time 도 중요하지만 swap 되는 양에 비례하여 transfer time이 대부분을 차지한다.
4-4. Dynamic Linking (동적 연결)
- linking(연결): 프로그래머가 작성한 소스 코드를 컴파일하여 생성된 목적 파일(object file)과, 이미 컴파일된 라이브러리 파일(library file)들을 묶어 하나의 실행파일을 생성하는 과정
- dyncamic linking: 컴파일을 통해 생성된 목적 파일과 라이브러리 파일 사이의 연결(= linking)을 프로그램의 실행 시점까지 지연시키는 기법
- Static linking(정적 연결)
- 프로그래머가 작성한 코드와 라이브러리 코드가 모두 합쳐져서 실행파일이 생성된다. 즉, 라이브러리가 프로그램의 실행 파일 코드에 포함되기 때문에 실행파일의 크기가 상대적으로 크다.
- 정적 연결에 사용되는 라이브러리는 static library
- 동일한 라이브러리 코드라 하더라도 각 프로세스의 주소 공간에 독자적으로 존재하는 코드이기 때문에 각 프로세스가 메모리에 적재해야 하므로 물리적 메모리가 낭비된다.
- 프로그래머가 작성한 코드와 라이브러리 코드가 모두 합쳐져서 실행파일이 생성된다. 즉, 라이브러리가 프로그램의 실행 파일 코드에 포함되기 때문에 실행파일의 크기가 상대적으로 크다.
- Dynamic linking(동적 연결)
- 라이브러리가 실행 시점에 연결된다. 즉 실행 파일에 라이브러리 코드가 포함되지 않으며, 프로그램이 실행되면서 라이브러리 함수를 호출할 때가 되어서야 라이브러리에 대한 연결이 이루어진다.
- 동적 연결에 사용되는 라이브러리는 shrared library
- stub(스텁): 동적연결을 가능하게 하기 위해 실행파일의 라이브러리 호출 부분에 해당 라이브러리의 위치를 찾기 위한 작은 코드
- 라이브러리 호출 시 스텁을 통해 해당 라이브러리가 메모리에 이미 존재하는지 살펴보고
- 존재하는 경우 그 주소의 메모리 위치에서 직접 참조
- 존재하지 않는 경우 디스크에서 동적 라이브러리 파일을 찾아 메모리로 적재한 후 수행
- 다수의 프로그램이 공통으로 사용하는 라이브러리를 메모리에 한 번만 적재하므로 메모리 사용의 효율성을 높일 수 있다.
- 운영체제의 지원이 필요하다.
- 라이브러리가 실행 시점에 연결된다. 즉 실행 파일에 라이브러리 코드가 포함되지 않으며, 프로그램이 실행되면서 라이브러리 함수를 호출할 때가 되어서야 라이브러리에 대한 연결이 이루어진다.
5. 물리적 메모리의 할당 방식
- 메모리는 일반적으로 OS 상주 영역과 사용자 프로세스 영역으로 나뉘어 사용된다.
- OS 상주 영역: 인터럽트 벡터와 함께 물리적 메모리의 낮은 주소 영역을 사용, 운영체제 커널이 위치
- 사용자 프로세스 영역: 물리적 메모리의 높은 주소 영역을 사용, 여러 사용자 프로세스들이 적재되어 실행
- 사용자 프로세스 영역의 할당 방법: 연속 할당(Contiguous allocation)과 불연속 할당(Noncontiguous allocation)
5-1. 연속 할당 (Contiguous allocation)
- 각각의 프로세스가 메모리의 한 곳에 연속적인 공간에 적재되도록 하는 것 → 주소 변환이 쉬웠음
- 외부 조각(External fragmentation)
- 프로그램의 크기 > 분할의 크기 - 분할이 비어 있는데도 프로그램을 적재하지 못함
- 아무 프로그램에도 배정되지 않은 빈 곳인데도 프로그램이 올라갈 수 없는 작은 분할
- 나중에 분할보다 작은 크기의 프로그램이 공간을 차지하게 되면 더 이상 외부조각이 아니고, 내부 조각이 발생할 수 있다.
→ 그때그때마다 조각에 대한 해석은 달라질 수 있다.
- 내부 조각(Internal fragmentation)
- 프로그램의 크기 < 분할의 크기 - 분할에 프로그램을 적재하고 남는 메모리 공간
- 하나의 분할 내부에서 발생하는 사용되지 않는 메모리 조각
- 특정 프로그램에 이미 배당된 공간으로 볼 수 있으므로 내부조각에 수용할 수 있는 충분히 작은 크기의 프로그램이 있다고 해도 공간을 활용할 수 없어 메모리가 낭비된다.
5-1-1. 고정 분할 방식 (Fixed partition allocation)
- 물리적 메모리를 고정된 크기의 분할로 미리 나누어두는 방식
- 분할의 크기는 모두 동일할 수도 있고 서로 다르게 할 수도 있다.
- 분할당 하나의 프로그램을 적재한다.
- 융통성이 없다.
- 동시에 메모리에 올릴 수 있는 프로그램의 수가 고정되어 있다.
- 최대 수행 가능 프로그램의 크기가 제한된다.
- 내부 조각과 외부 조각 발생
5-1-2. 가변 분할 방식 (Variable partition allocation)
- 분할을 미리 나누어 놓지 않은 채 프로그램이 실행되고 종료되는 순서에 따라 분할을 관리하는 방식
- 메모리에 적재되는 프로그램의 크기에 따라 분할의 크기, 개수가 동적으로 변함
- 프로그램의 크기를 고려해서 메모리를 할당하고 기술적으로 관리할 수 있는 기법이 필요하다.
- 외부 조각만 발생
- Hole(= 가용 메모리 공간, 비어있는 메모리 공간)
- 다양한 크기의 hole들이 메모리 여러 곳에 흩어져 있다.
- 프로세스가 도착하면 수용가능한 hole을 할당
- 운영체제는 할당 공간과 가용 공간(hole)에 대한 정보를 유지한다.
- 가용 공간에 새로운 프로그램을 할당하면 → 할당 공간이 되고 할당 공간의 프로그램이 종료되면 → 가용 공간이 된다.
- 동적 메모리 할당 문제(dynamic storage-allocation problem)
- 가변 분할 방식에서 size n인 요청을 만족하는 가장 적절한 hole을 찾는 문제
- First-fit(최초 적합): Size가 n 이상인 것 중 최초로 찾아지는 hole에 할당
- hole을 모두 탐색하는 방법이 아니므로 시간적인 측면에서 효율적
- Best-fit(최적 적합): Size가 n 이상인 것 중 가장 작은 hole을 찾아 할당
- hole들의 리스트가 크기순으로 정렬되어 있지 않은 경우에 모든 hole 리스트를 탐색 → 시간적 오버헤드가 발생
- 많은 수의 아주 작은 가용공간들이 생성됨
- Worst-fit(최악 적합): Size가 n 이상인 것 중 가장 큰 hole에 할당
- 모든 hole 리스트를 탐색해야 하는 오버헤드 발생
- 상대적으로 더 큰 프로그램을 담을 수 있는 hole을 빨리 소진
- First-fit과 best-fit이 worst-fit보다 속도와 공간 이용률 측면에서 효과적
- 외부 조각 문제를 해결하기 위한 방법: Compaction(컴팩션)
- 사용 중인 메모리 영역을 한 군데로 몰고 hole들을 다른 한쪽으로 모아서 하나의 큰 block을 만드는 방법
- 수행 중인 프로세스의 메모리상의 위치를 이동시키는 작업이라 매우 비용이 많이 드는 방법
- 전체 프로그램의 바인딩과 관련된 문제, Execution time binding이 지원되는 환경에서만 수행
5-2. 불연속 할당 (Noncontiguous allocation)
- 하나의 프로세스가 메모리의 여러 영역에 분산되어 적재될 수 있는 것
5-2-1. Paging(페이징 기법)
- 프로세스의 주소 공간을 동일한 크기의 페이지 단위로 나누어 물리적 메모리의 서로 다른 위치에 페이지들을 저장하는 방식
5-2-2. Segmentation(세그먼테이션)
- 프로세스의 주소 공간을 의미 단위의 세그먼트로 나누어 물리적 메모리에 올리는 방식
5-2-3-. Paged Segmentation(페이지드 세그먼테이션)
[복습]
- 논리적 주소(logical address): 그 프로세스를 위해 생성되는 독자적인 주소 공간, CPU가 보는 주소
- 물리적 주소(physical address): 물리적 메모리에 실제로 올라가는 위치, 0 번지부터 통으로 관리
- 주소 바인딩(address binidng): 프로세스의 논리적 주소를 물리적 메모리 주소로 연결시켜 주는 작업
- 컴파일 타임 바인딩: 프로그램을 컴파일할 때 결정, 절대 코드, 0번지부터 시작
- 로드 타임 바인딩: 프로그램의 실행이 시작될 때 결정, 종료될 때까지 위치 고정, 재배치 가능 코드
- 실행 타임 바인딩(런타임 바인딩): 프로그램이 실행을 시작한 후에도 그 프로그램이 위치한 물리적 메모리상의 주소가 변경 가능, 주소 매핑 테이블을 이용해 바인딩 점검, MMU
- MMU(memory management unit): 논리적 주소를 물리적 주소로 매핑해 주는 하드웨어 장치
- 논리적 주소 + relocation register 값 = 물리적 주소 값
- relocation register(물리적 메모리 시작 주소), limit register(프로세스의 크기)
- 동적 로딩: 실행에 필요한 부분이 실제로 불릴 때마다 메모리에 적재하는 것
- 중첩: 프로세스의 주소 공간을 분할해 실제 필요한 부분만을 메모리에 적재하는 것(단일 프로세스만)
- 스와핑: 수행 중인 프로세스의 주소 공간을 일시적으로 메모리에서 내려놓는 것
- 동적 연결: 프로그램이 실행되면서 라이브러리 함수를 호출할 때가 되어서야 라이브러리에 대한 연결이 이루어지는 것
- 물리적 메모리의 할당 방식 - 연속할당: 각각의 프로세스가 메모리의 한 곳에 연속적인 공간에 적재되도록 하는 것
- 고정 분할 방식: 물리적 메모리를 고정된 크기의 분할로 미리 나누어두는 방식, 내부 외부 조각 모두 발생
- 가변 분할 방식: 분할을 미리 X, 프로그램이 실행되고 종료되는 순서에 따라 분할을 관리하는 방식, 외부 조각만 발생
- first-fit, best-fit, worst-fit, compaction
이화여자대학교 반효경 교수님의 [2014년 1학기 운영체제] 강의 정리입니다.
반효경 교수님의 [운영체제와 정보기술의 원리] 교재를 참고하였습니다. 감사합니다.
https://core.ewha.ac.kr/publicview/C0101020140425151219100144?vmode=f
728x90
'CS > 운영체제' 카테고리의 다른 글
[운영체제] Chapter 8. Memory Management (4) (0) | 2023.01.18 |
---|---|
[운영체제] Chapter 8. Memory Management (2), (3) (0) | 2023.01.16 |
[운영체제] Chapter 7. Deadlock (1), (2) (0) | 2023.01.05 |
[운영체제] Chapter 6. Process Synchronization, Concurrency Control (병행 제어) (0) | 2022.12.28 |
[운영체제] Chapter 6. Process Synchronization (3) (2) | 2022.12.28 |