티스토리 뷰

김주균, OS? Oh Yes! (휴먼싸이언스, 2008)

프로그램을 짜고, 실행시키면서 프로그램 용량이 커서 메모리에 들어가지 못할 것이라는 걱정을 하는 사람은 없음

➡ 시스템이 사용자 프로그램을 메모리의 어디에, 어떻게 넣을지, 수용 공간까지 알아서 해결

 

운영체제는 메모리 크기 아래 프로그램을 작은 조각으로 나누어 일부분만을 메모리에 적재

➡ 보다 많은 사용자 수용, 사용자가 메모리 크기로부터 자유로움

➡ 제한적인 크기지만 엄청나게 큰 메모리가 있는 것처럼 여겨지기 때문에 가상(Virtual) 메모리라고 함

 

8.1 가상 메모리 (Virtual Memory)를 위해서는

프로그램은 작은 조각으로 이루어짐

조각 크기 같도록 ➡ 페이지(Page)

조각 크기 다르게 ➡ 세그먼트(Segment)

이 크기가 메모리와 디스크 사이에 한 번에 전송되는 전송 단위가 되는데, 이를 블록(Block)이라고 부름

- 페이지로 나눌 때 : 페이징 / 세그먼트로 나눌 때 : 세그먼테이션 시스템

 

가상 메모리의 관리를 위해 주소의 사상 (Address Mapping)이 해결되어야 함

- 실행 프로그램에서 참조하는(Referenced) 용어는 발생되는, 또는 생성되는 등의 말로도 표현

- 주소가 실제 메모리에 있는 주소와 달라, 메모리상의 주소로 변환이 필요할 때 하는 것이 사상 ⬅ mapping

 

프로그램에서 참조하는 주소 ➡ 가상 주소(Virtual Address)

실제 메모리상의 주소 ➡ 실주소(Real Address)

주소의 지정이 다른 이유는?

- 주소의 지정이 컴파일 시에 이루어진다는 의미 : 프로그램이 실행될 때 참조하는 주소가 컴파일될 때 지정

- 참조하는 주소가 실주소이기 때문에 프로그램은 항상 메모리의 지정된 곳으로만 적재되어야 함

 

재배치 : 메모리에서의 위치를 적재될 때마다 바꿀 수 있음

- 융통성, 메모리의 효율적인 이용이란 장점

- 프로그램 전부가 통째로, 연속적으로 메모리에 적재되어야 함

- 컴파일 시에 주소는 위치값 (Offset, Distance) : 첫 번째 줄을 0으로 하고 나머지들 전부는 첫 번째 줄로부터 얼만큼의 위치에 있는지 값으로 지정

- 실행 시에 참조되는 주소 ➡ 프로그램 내에서 어느 정도의 위치에 있는 지를 나타내는 상대주소(Relative Address)

- 실주소 ➡ 메모리에 적재될 때의 시작 주소(Start Address) + 상대주소 값

- 상대주소로부터 실주소의 변환이 요구되고, 이는 재배치 레지스터 값(시작 주소)을 상대주소에 더하기만 하면 됨

 

가상 메모리로 관리될 때 프로그램은 디스크에 조각난 모양으로 저장 (연속적일 필요 X)

- 몇개가 메모리에 비연속적으로 다른 프로그램의 조각들과 섞여 적재 ➡ 다중 프로그래밍

 

- 실행 중인 프로그램에서 참조하는 주소 (가상주소)는 참조하고자 하는 명령어나 변수 등이 자신의 프로그램 내에서 몇 번째 조각에 있으며, 그 조각 내에서 어느 위치(Offset)에 있는지 알려줌

 

- 소스 프로그램에서 goto 10 명령어
- 라벨 10으로 지정되었고 프로그램이 컴파일 된 후 실행 코드(Executable Code)의 형태에서 3번째 조각의 5번째 위치
- 주소를 나타내는 10 ➡ <3, 5>
- goto 명령어 실행되면 가상주소로 <3, 5> 참조되고 이 값으로 사상 과정을 거쳐 goto 해야 할 명령어의 실제 메모리 주소를 알게 됨
- 대부분의 시스템에서 첫번째 조각과 조각 내의 값을 0으로 시작, <2, 4>가 맞지만 다른 사상에서 이해

 

8.2 페이징 (Paging)

페이징을 위해서는 모든 프로세스들이 같은 크기의 조각들로 나뉘어야 함 ➡ 한 조각을 페이지

메모리 역시 프레임(Frame)이라고 불리는 페이지와 같은 크기로 나누어져 있으며 일련 번호가 매겨짐

- 페이지의 크기는 일반적으로 수 KByte 정도, 주소 체계를 생각할 때 2의 승수 배 크기로 잡음

 

프로세스의 실행이 진행되는 과정에 따라 디스크와 메모리를 오가며 교체되는 단어가 페이지이며, 이것은 곧 사상의 단위가 됨

운영체제는 가상주소를 실주소로 변환하기 위해 프로세스당 하나의 페이지 테이블 ➡ 사상 테이블(Map Table)

- 위 테이블의 크기는 해당 프로세스의 페이지 개수에 비례

- k개의 페이지를 가지는 프로세스의 페이지 테이블은 k개의 엔트리(Entry)로 구성, 엔트리 하나는 4byte

- 한 프로세스에서 나뉘는 페이지는 일련번호 가짐

- 페이지 테이블은 이 번호 순서대로 엔트리 배치

- 테이블에서 첫 번째 엔트리는 프로세스의 첫 번째 페이지를 위한 사상 정보 가짐

 

엔트리 정보

- 페이지가 메모리에 적재되어 있는가를 나타내는 존재(Residence) 비트로서 적재된 경우 1, 아닐 경우 0의 값을 가짐

- 1의 경우 : 적재되어 있는 프레임 번호

- 0의 경우 : 페이지가 저장되어 있는 디스크의 주소를 나타내는 필드

 

실행 시 참조되는 가상주소는 페이지 번호(p)와 페이지 내에서의 위치(d)로 표시

- 페이지 테이블은 메모리 커널 영역에 보관

- 실행 중인 프로세스의 테이블 시작주소는 페이지 테이블 기준 레지스터(Page Table Origin Register)에 들어있음

- 기준 레지스터 값에 p를 더해 페이지 테이블에서 페이지 p의 사상 정보를 갖고 있는 엔트리를 찾은 후, 존재 비트 확인

- (정확하게 말하면 p와 엔트리 크기를 곱한 값을 더하는 것, 메모리는 워드 단위로 주소가 붙여지므로 워드의 크기나 엔트리의 크기를 같게 하는 경우는 p만 더해도 해당 엔트리를 찾게 됨)

 

존재 비트가 1일 경우

- p가 적재되어 있는 프레임 번호(f)를 알 수 있음

- 이 번호 값에 페이지 크기를 곱하면 메모리에서 이 프레임의 시작수조를 알게 되고 여기에 d를 더하면 프레임 내에서 접근해야 할 워드의 주소 즉, 실주소로 접근하게 되는 것

- p x (f - 1) + d

 

존재 비트가 0일 경우

- 접근하고자 하는 워드를 포함하는 페이지가 메모리에 없는 것

- 실행을 계속하기 위해서 디스크 주소로부터 이 페이지를 메모리에 적재

- 엔트리의 존재 비트를 1로 바꾸고, 적재된 프레임 번호를 기입한 후 사상을 계속 진행하면 실주소 얻게 될 것

 

- 운영체제는 정확한 사상을 위해 변동이 있을 때마다 페이지 테이블을 갱신, 관리하고 있어야 함

- 페이지들의 적재와 교체 등을 위해 메모리의 빈 프레임에 관한 정보 역시 유지, 관리해야 함

- 페이지의 메모리 적재는 프레임과 크기가 같으므로 빈 프레임만 있다면 아무거나 할당

 

8.2.1 TLB(Translation Lookaside Buffer)의 사용

TLB : 고속 캐시의 일종, 주소로 접근되는 일반 메모리와 달리 키(Key) 값으로 찾고자 하는 워드를 동시에 접근하는 연관 메모리

- 검색이 빠른 반면 비싼 하드웨어

- 페이지 테이블을 메모리에 두고 접근할 때의 느림을 극복하기 위해 사용

- 용량을 크게 할수록 좋지만 가격대비 성능을 따져 페이지 테이블의 일부 엔트리만 수용하는 크기로 두는 것이 보편적

 

- 최근에 빈번하게 검색된 엔트리들을 TLB에 넣되, 페이지 번호(p)를 키 값으로 동시 검색을 하므로 TLB에 저장되는 각 엔트리는 페이지 번호도 함께 표시되어야 함

- 가상주소의 p를 키 값으로 먼저 TLB부터 검색하며, 페이지 번호를 p로 가지고 있는 엔트리가 있을 경우 그 엔트리에 적혀 있는 프레임 번호를 가지고 실주소에 이르는 과정은 페이징과 같음

- 검색되는 엔트리들의 페이지는 모두 메모리에 적재되어 있으므로 존재 비트를 확인할 필요가 없음

- TLB에서 p를 가지는 엔트리의 검색에 실패하면 메모리에 있는 페이지 테이블로부터 사상이 진행되어 실주소를 얻게 되고, 이 엔트리는 TLB에 추가

 

- TLB의 사용으로 실주소로의 접근 시간이 빨라지기 위해서는 원하는 엔트리가 TLB에서 발견되는 확률이 높을수록 좋음

- TLB의 검색 성공 확률 : 적중률(hit ratio)

 

ex) TLB 검색과 메모리 접근에 각각 20과 100나노 초가 걸리고 적중률이 90%일 때

- 실주소로 메모리를 접근하는데 걸리는 시간 : 실 접근 시간(Effective Access Time)

- 실 접근 시간은 0.9 x 120(TLB 접근 + 실주소 접근) + 0.1 X 220(TLB 접근 + 사상 테이블 접근 + 실주소 접근) = 130

- TLB를 사용하지 않았을 경우의 200나노 초보다 빠른 것을 알 수 있음

 

8.2.2 페이지의 보호(Protection)와 공유(Sharing)

- 접근하고자 하는 페이지에 대해 읽거나 쓰기 작업을 어떻게 제한할 것인가와 다른 프로세스의 주소 공간으로 침범하지 못하도록 하는 것 : 보호의 영역

- 페이지 테이블의 각 엔트리에 해당 페이지에 대한 보호 비트(Protection Bits)를 두어 허용되는 접근 설정

- 쓰기작업에 대한 보호 비트의 값이 1 : 쓰기 허용 / 0일 경우 : 쓰기 시도는 보호에 위반되므로 트랩 일으킴

- 프로세스가 사상을 거쳐 해당 페이지가 적재된 프레임의 시작주소를 알게된 후, 여기에 더해지는 offset이 페이지의 크기를 넘게 되면, 다른 프레임의 접근을 의미 ➡ 트랩을 통한 보호 필요

- 페이징에서의 주소 공간 보호는 offset의 크기가 페이지의 크기를 넘지 않으면 안전

 

공유 : 사용자들이 편집이나 컴파일 같은 작업은 그 프로그램 한 부만 메모리에 두고 실행해 줌으로써 메모리 공간 절약

- 다수의 사용자가 한 부의 응용 프로그램을 공유하여 실행한다는 것은 공유 프로그램 내에서 각자의 실행 위치가 다른 한편, 사용되고 만들어지는 각자의 데이터는 자신들의 주소 공간에 가지도록 함

- 공유되는 프로그램은 코드의 내용이 변하지 않도록 재진입 코드(Reentrant, Pure Code)로 컴파일

 

- 페이징에서의 공유 : 프로세스 각자의 페이지 테이블에서 엔트리에 같은 프레임 번호를 가지도록 함으로써 쉽게 구현할 수 있음, 프로세스들이 사상을 거쳐 같은 프레임을 접근하도록 함으로써 그 프레임에 적재된 페이지를 거쳐 공유하게 되는 것

- 페이지는 코드 페이지와 데이터 페이지로 나눌 수 있음

- 코드 페이지 : 명령어를 가지므로 가상주소를 참조 / 데이터 페이지 : 그럴 일이 없음

- 코드 페이지가 공유되기 위해서는 재진입 코드여야 함

 

공유 페이지는 각 table에서 같은 위치

- 페이지 테이블은 동일해야 함

- 위치가 다르다는 말은 goto 명령어를 실행하는 프로세스마다 가상주소의 페이지 번호가 다를 수 있다는 말과 같고, 이것은 어떤 프로그램이 실행하는 프로세스에 따라 명령어가 접근하는 주소가 달라진다는 경우를 말함

- 공유 페이지의 엔트리 위치를 서로 다르게 하는 것도 가능은 하지만 까다로운 관리 요구

 

8.2.3 페이징에서 사상 테이블의 구성

- 32비트를 사용해 주소를 표현하는 시스템에서 하위 12비트를 offset으로 사용

➡ 페이지의 크기는 4Kbyte가 된고 사상 테이블은 최대 100개의 엔트리를 가질 수 있을 것

 

- 엔트리의 크기를 4Byte로 잡더라도 페이지 테이블의 크기는 4Mbyte가 되므로 매우 큰 크기가 되어 메모리에 모두 저장하기에는 벅차게 되므로, 페이지 테이블을 작게 나누어 필요한 부분만을 메모리에 적재하기 위해 계층구조를 갖도록 구성할 수 있음

- 계층구조인 2단계 페이징 : 위에서 말한 페이지 번호를 나타내는 20비트를 10비트씩 나누어 상위 10비트를 바깥 페이지 테이블의 엔트리 위치로, 하위 10비트는 나누어진 테이블 내의 엔트리 위치를 나타내도록 한다면?

➡ 메모리에 상주시키는 4Kbyte 크기의 루트 테이블과, 같은 크기의 1024개 페이지 테이블들의 선택적인 메모리 적재를 통해 전부 적재해야 하는 부담 줄임

 

 

- 1024개의 엔트리를 가지는 루트 테이블 한 개와, 1024의 엔트리를 가지는 페이지 테이블에서의 사상과정을 보여줌

- 루트 테이블의 시작주소는 기준 레지스터에 들어있고 루트 테이블의 각 엔트리는 해당 페이지 테이블의 시작주소를 가지도록 구성

- 메모리의 고정 크기의 페이지 테이블 하나만 둠으로써 해결하는 방법도 있음 ➡ 역 페이지 테이블이라고 함

- 역 페이지 테이블 : 메모리의 프레임 수만큼 엔트리를 가지며, 테이블 내에서 엔트리의 순서는 프레임의 순서와 같음

- k번째 엔트리는 메모리의 k번째 프레임에 대한 사상 정보를 가지고 있는데, 빈 프레임인지 아닌지를 나타내는 존재 비트와 함께 적재된 경우 어떤 프로세스의 몇 번째 페이지인지를 나타내게 됨

- 역 페이지 테이블을 사용할 때의 가상주소는 페이지 번호(p), 위치 값(d)과 함께 이 페이지를 소유하는 프로세스 번호(Pid)도 가져야 함 ➡ 사상을 할 때 프로세스 번호와 페이지 번호를 함께 사용하여 페이지 테이블을 검색해야 하기 때문

 

- 역 페이지 테이블을 사용하면 프레임마다 적재한 프로세스 번호를 가져야 하므로, 서로 다른 프로세스번호를 필요로 하는 공유는 구현하기 매우 힘듬

- 페이징 : 고정 크기의 페이지로 메모리를 관리함으로써 구현이 쉬움 ⬅ 대부분 시스템에서 채택

- 프로그램의 마지막 페이지는 내부 단편화가 있게 됨

 

8.3 세그먼테이션 (Segmentation)

대부분 프로그램은 main 프로그램, 프로시저, 함수, 전역 또는 지역변수와 호출 시 사용되는 스택 등으로 이루어짐

➡ 세그먼트 : 논리적으로 하나하나의 단위로 구분이 가능한 서로 다른 크기들이 모여 전체 프로그램 구성

➡ 이런 단위대로 사상하거나 적재하는 기법 : 세그먼테이션

 

- 프로그램은 서로 크기가 다른 세그먼트들로 이루어지며, 세그먼트 개수만큼의 엔트리를 가지는 세그먼트 테이블이 있어야 함

- 가상주소는 세그먼트 번호(s)와 세그먼트 내에서의 위치 값(d)으로 표현

- 세그먼트 테이블에서 한 엔트리가 가지는 정보는 존재 비트

- 존재 비트의 값에 따라 유효한 디스크 주소와 메모리 주소 갖는 필드 있음

- 세그먼트의 실행을 제어할 때 사용하는 몇 개의 비트들을 구현에 따라 설정 가능

- 접근 제어 키(Access Control Key) : 해당 세그먼트에 대해 정교하게 제어할 수 있음

 

- 페이징에서는 적재된 프레임 번호가 알려지는 반면, 여기서는 엔트리에 해당 세그먼트가 적재된 메모리의 시작주소가 적혀 있음

- 다양한 크기의 수용을 위해 배치(fit) 기법 사용

- TLB를 사용하거나 테이블의 구성을 다단계 또는 역 페이지 등과 같이 하는 것은 세그먼테이션에서도 똑같이 가능함

'❄️ Sookmyung > 📱 OS? Oh Yes!' 카테고리의 다른 글

[Operating System] 프로세스와 스레드  (0) 2022.10.12
Comments