메모리 계층 구조
메모리는 컴퓨터 시스템 여러 곳에 계층적으로 존재한다
- CPU 레지스터 -> CPU 캐시 -> 메인 메모리 -> 보조기억장치
- 보조기억장치로 갈수록 가격이 저렴해지고 속도가 느려지며 용량이 증가
레지스터 | L1/L2 cache | L3 cache | 메인 메모리 | 보조기억장치 | |
용도 | 몇 개의 명령과 데이터 저장 | 한 코어에서 실행하는 명령과 데이터 저장 | 멀티 코어들에 의해 공유되는 명령과 데이터 저장 | 실행중인 프로세스의 코드, 데이터와 입출력중인 파일 블록들 저장 | 파일, DB, 메모리에 적재된 코드, 데이터의 영구 저장 |
용량 | byte 단위로 8~30개정도 존재 1KB 미만 |
KB단위 | MB단위 | GB단위 | TB단위 |
타입 | SRAM | SRAM | DRAM | 마그네틱 필드나 플래시 메모리 | |
속도 | < 1ns | < 5ns | < 5ns | < 50ns | < 20ms |
가격 | 고가 | 고가 | 보통 | 저가 | |
휘발성 | 휘발성 | 휘발성 | 휘발성 | 휘발성 | 비휘발성 |
계층화 목적과 과정
- 메모리 액세스 시간을 줄여 빠른 프로그램의 실행을 위해 계층화 시도
- CPU의 성능 향상 -> 더 빠른 메모리의 필요성 -> 작지만 빠른 off-chip cache 적용 -> 더 빠른 액세스를 위해 on-chip cache를 적용 -> 멀티코어 시스템에 적합한 L1, L2, L3 cache 적용
-> off-chip cache란 CPU 외부에 존재하는 캐시메모리
-> on-chip cahce란 CPU 내부에 존재하는 캐시메모리로 물리적으로 거리가 가까우므로 off-chip cache보다 액세스가 빠름
계층화 성공 이유
매우 작은 용량의 캐시에 당장 실행할 코드의 일부분만 담아두어도 효과적일까?
효과적인 이유
-> 참조의 지역성 때문(Locality of reference)
- 코드나 데이터, 자원 등이 아주 짧은 시간 내에 다시 사용되는 특성 때문에 효과적
-> 오버헤드의 정도
- 캐시를 채우는데 생기는 오버헤드보다, 매우 빠른속도의 캐시메모리를 이용하는 이득이 더 큼
운영체제의 메모리 관리가 필요한 이유
- 메모리는 공유자원
- 여러 프로세스 사이에 메모리를 공유함
- 한 프로세스가 메모리를 독점하면 당연히 다른 프로세스는 실행될 수 없으므로 메모리는 공유되어야 함
- 각 프로세스에 물리 메모리를 할당해야함 - 메모리는 보호되어야 함
- 다른 프로세스로부터 보호받기 위해 프로세스별 독립된 메모리 공간을 보장해야 함
- 사용자 코드로부터 커널 공간을 보호 받아야 함 - 메모리 용량 한계 극복 필요
- 설치된 물리 메모리보다 큰 프로세스를 실행하기위한 지원 필요
- 여러 프로세스의 메모리 합이 설치된 메모리보다 큰 경우 한계 극복 필요 - 메모리 효율성 증대 필요
- 가능하면 많은 개수의 프로세스를 실행시키기 위해
물리주소와 논리주소
- 물리주소(Physical Address)
- 물리 메모리(RAM)에 매겨진, 하드웨어에 의해 고정된(Fixed) 메모리 주소
- 0에서 시작하여 연속되는 주소 체계
- 메모리는 시스템 주소 버스를 통해 물리 주소의 신호를 받음(32bit의 경우 2^32개의 주소 지정 가능) - 논리주소(Logical Address / Virtual Address)
- 개발자나 프로세스가, 프로세스 내에서 사용하는 주소로 코드, 데이터, 힙, 스택과같은 영역에 대한 주소
- 0에서 시작하여 연속되는 주소 체계, 물리주소와 달리 프로세스 내에서 매겨진 상대적 주소
- 컴파일러와 링커에 의해 매겨진 주소
- CPU 내에서 프로세스를 다루는 동안 사용하는 모든 주소는 논리주소
- 사용자나 프로세스는 절대 물리주소를 알 수 없음
- 논리주소와 물리주소 사이의 매핑 테이블은 프로세스마다 있음 - MMU(Memory Management Unit)
- 논리주소를 물리주소로 바꾸는 하드웨어적 장치
- CPU가 발생시킨 논리주소는 MMU에 의해 물리주소로 바뀌어 물리메모리에 접근
- 오늘날 MMU는 CPU에 내장되며 MMU덕분에 여러 프로세스가 하나의 물리메모리에 충돌없이 실행됨
- 매핑테이블을 이용하여 주소 변환
컴파일과 논리주소
- 컴파일러는 프로그램을 논리주소로 컴파일
- 코드, 데이터, 힙, 스택을 0번지부터 시작하는 논리 주소에 할당 - 응용프로그램 적재 시
- 운영체제는 프로그램을 보조기억장치로부터 물리메모리의 적절한 위치(비어있는)에 적재
- 논리주소와 물리주소의 매핑 테이블 생성 - 응용프로그램 실행 시(프로세스)
- CPU가 인지하는 모든 주소는 논리주소(CPU는 이미 컴파일된 명령들을 다루기 때문)
- MMU는 CPU로부터 발생되는 논리주소를 물리주소로 변환(매핑 테이블 참조)
- 함수가 호출될 때 사용되는 스택 주소 역시 논리 주소
ASLR(Address Space Layout Randomization)
- 해커들의 메모리 공격에 대한 대비책으로 오늘날 대부분의 운영체제가 사용
- 주소 공간을 랜덤으로 배치
- 프로세스의 주소 공간 내에서 스택, 힙, 라이브러리 영역을 랜덤으로 배치(실행마다)
- 실항할 때 마다 논리 주소가 바뀌게 하는 기법
- 스택, 힙에 대해 적용하여 함수의 지역변수와 동적할당 받는 공간의 논리 주소가 실행시마다 바뀜
- 코드영역이나 데이터영역, 전역변수의 논리주소는 바뀌지 않음
메모리 할당(Memory Allocation)
- 운영체제가 새 프로세스를 실행시키거나(적재), 실행중인 프로세스가 메모리를 필요로 할 때(힙, 스택 영역 확장 등) 물리 메모리를 할당
메모리 할당 기법
- 연속 메모리 할당 : 프로세스 별 한 덩어리의 메모리 할당
- 고정 크기 할당
-> 메모리를 고정크기의 파티션으로 미리 나누고, 프로세스 당 하나의 파티션을 할당
-> 파티션의 크기는 모두 같거나 다를 수 있음
-> 나눠진 파티션 중 프로세스 크기에 가장 가까운 파티션을 할당
- 가변 크기 할당
-> 메모리를 가변 크기의 파티션으로 나누고, 프로세스 당 하나의 파티션을 할당
-> 고정 크기 할당과 다르게 미리 나누지는 않음
-> 프로세스 크기나 요청에 따라 동적으로 할당 - 분할 메모리 할당 : 프로세스에게 여러 덩어리의 메모리 할당
-> 연속 메모리 할당은 프로세스 하나별로 연속된 메모리를 할당하므로 유연성이 부족함
-> 할당된 프로세스 사이 사이에 빈 공간을 합치면 새 프로세스를 할당할 수 있음에도, 공간이 부족하여 할당하지 못함
-> 이를 해결하기 위해 프로세스 별 연속된 1개의 덩어리가아닌, n개의 작게 쪼개진 덩어리들을 할당
- 고정 크기 할당
-> 고정 크기로 나눠진 메모리를 여러 개로 분산 할당 -> 페이징(Paging)기법
-> 모든 프로세스를 page라고 불리는 고정 크기 단위로 분할, 물리 메모리의 frame에 적재
- 가변 크기 할당
-> 가변 크기로 나눠진 메모리를 여러 개로 분산 할당 -> 세그멘테이션(Segmentation)기법
-> 코드, 데이터, 힙, 스택 등을 세그먼트로 나눠 적재
-> 세그먼트들의 크기가 각기 달라 외부 단편화 초래 가능
연속 메모리 할당
연속 메모리 할당은 초기 운영체제에서 사용됨
- 단일 프로세스 시스템
- 한 프로세스가 전체 메모리를 독점하는 방식(MS-DOS) - 고정 크기 할당
- IBM OS/360 MFT
- 메모리 전체를 n개의 고정된 크기로 분할, 하나의 프로세스에 하나씩 할당
- 수용 가능 프로세스는 n개로 고정
- 메모리가 부족하면 프로세스는 큐에서 대기 - 가변 크기 할당
- IBM OS/360 MVT
- 프로세스마다 프로세스 크기만큼의 연속 메모리 할당
- 수용가능한 프로세스의 수는 크기에 따라 가변적
- 메모리가 부족하면 프로세스는 큐에서 대기
-> 전부 가상메모리 기법은 지원하지 않음
단편화
- 프로세스에게 할당할 수 없는 작은 조각 메모리들이 생기는 현상, 이 조각 메모리를 홀(Hole)이라고 부름
- 내부 단편화(Internal fragmentation)
- 고정되어 할당된 메모리 내부에 사용할 수 없는 홀이 생기는 현상
- 파티션보다 작은크기의 프로세스를 할당하는 경우, 파티션 내에 홀이 발생
- IBM OS/360 MFT - 외부 단편화(External fragmentation)
- 가변 크기로 할당된 메모리들 사이사이에서 사용할 수 없는 홀이 생기는 현상
- 프로세스와 프로세스 사이의 홀이 새로 적재할 프로세스보다 작으면 할당할 수 없음
- IBM OS/360 MVT
연속 메모리 할당 구현
- 하드웨어의 지원
- CPU에 담당 레지스터가 필요
- base 레지스터 : 현재 실행중인 프로세스에게 할당된 물리메모리 시작 주소
- limit 레지스터 : 현재 실행중인 프로세스에게 할당된 메모리의 크기
- 주소 레지스터 : 현재 액세스하려는 메모리의 논리 주소
- MMU 필요 - 운영체제의 지원
- 프로세스별 할당된 물리메모리 시작 주소와 할당된 메모리의 크기 정보를 저장, 관리
- 비어있는 메모리 영역 관리
- 새 프로세스를 스케줄링하여 실행할 때 마다, 물리 메모리 시작 주소와 할당된 메모리의 크기 정보를 CPU 내부 base레지스터와 limit 레지스터에 적재
연속 메모리 할당의 장단점
- 장점
- 논리주소를 물리주소로 바꾸는 과정이 단순, CPU의 메모리 액세스 속도가 빠름(나누어진 것이 아닌 하나의 덩어리이므로)
- 운영체제가 관리할 정보량이 적어서 부담이 덜함 - 단점
- 메모리 할당의 유연성이 떨어짐. 작은 홀들을 합쳐 충분한 크기의 메모리가 있어도 연속된 메모리를 할당할 수 없는 상황 발생 -> 메모리 압축 기법으로 해결
홀 선택 알고리즘
- 운영체제는 메모리가 할당된 위치, 크기, 비어있는지 유무 등의 할당된 파티션에 관한 정보를 유지 관리
- 이 정보들을 포함한 리스트를 할당 리스트라고 함(Allocation list)
할당 요청에 관한 운영체제의 홀 선택 전략
- 최초적합(First-Fit)
- 홀 리스트를 검색하여 처음으로 만나는 할당 가능한 크기의 홀을 선택
- 할당 속도는 빠르나, 단편화 발생 가능 - 최적적합(Best-Fit)
- 홀 리스트를 검색하여 할당 가능한 홀 중에서 가장 작은 홀을 선택
- 크기별로 홀이 정리되어있지 않으면 전부 검색해야하므로 오버헤드가 큼 - 최악적합(Worst-Fit)
- 홀 리스트를 검색하여 할당 가능한 홀 중에서 가장 큰 홀을 선택
- 크기별로 홀이 정리되어있지 않으면 전부 검색해야하므로 오버헤드가 큼
- 거의 사용되지 않음
세그멘테이션
- 세그멘트(Segment) : 프로그램을 구성하는 논리적 단위로 각각 의미와 용도를 가짐
- 일반적인 세그먼트의 종류로 코드 세그멘트, 데이터 세그멘트, 힙 세그멘트, 스택 세그멘트가 있음 - 세그멘테이션 기법
- 프로세스를 논리 세그멘트로 나누고, 각 세그멘트를 물리 메모리(물리 세그멘트)에 할당하는 메모리관리 기법 - 프로세스의 주소 공간
- 프로세스의 주소공간은 여러 개의 논리 세그멘트들로 구성
- 각 논리 세그멘트는 물리 세그멘트에 매핑
- 프로세스를 논리 세그멘트로 나누는 과정은 컴파일러와 링커에 의해 이루어짐
- 컴파일러와 링커는 응용프로그램과 라이브러리의 코드를 모아 코드 세그멘트를 구성, 전역변수를 모아 데이터 세그멘트 구성
- 운영체제 로더는 실행 파일에 구성된 각 논리 세그멘트를 물리 세그멘트에 할당, 논리 세그멘트 적재 - 논리 세그멘트와 물리 세그멘트의 매핑
- 시스템 전체에 1개의 세그멘트 테이블을 두고 논리주소를 물리주소로 변환 - 외부 단편화 발생 가능
- 세그멘트들의 크기가 같지 않기 때문에, 세그멘트들 사이에 홀이 발생
- 필요한 만큼만 할당하므로 내부 단편화는 발생하지 않음
세그멘테이션의 구현
- 하드웨어의 지원
- 논리 주소 구성 : [세그멘트 번호, 오프셋]
- 오프셋 : 세그멘트 내의 상대 주소, 어떤 기준점으로 부터 얼마나 멀어져있는지를 나타내는 값(메모리 침범 방지)
- CPU : 세그멘트 테이블의 시작 주소를 가리키는 레지스터 필요(Segment Table Base Register, STBR)
- MMU 필요 : 논리 주소가 세그먼트 범위를 넘는지 판별(오프셋 이용), 논리주소를 물리주소로 변환(메모리 할당)
- 세그멘트 테이블 : 메모리에 저장, 세그멘트별 시작 물리주소(base), 세그멘트 크기 정보 저장(limit) - 운영체제의 지원
- 세그멘트의 동적 할당/반환 및 세그멘트 테이블 관리 기능 구현
- 프로세스의 생성/소멸에 따라 동적으로 세그멘트 할당/반환
- 물리 메모리에 할당된 세그멘트 테이블과 자유 공간에 대한 자료 유지
- 컨텍스트 스위칭 때 CPU 레지스터에 적절한 값 로딩 - 컴파일러, 링커, 로더의 지원
- 사용자 프로그램을 세그멘트 기반으로 컴파일, 링킹, 로딩
'운영체제' 카테고리의 다른 글
페이징 메모리 관리 (0) | 2024.06.04 |
---|---|
교착 상태(Dead Lock) (1) | 2024.06.03 |
스레드 동기화 (1) | 2024.06.03 |
CPU 스케줄링 (2) | 2024.06.02 |