* 이 글은 학부생 시절 개인 Notion에 작성했던 강의 필기 노트를 Velog에 옮긴 글입니다.
📗: 운영체제 제10판 | Abraham Silberschatz, Peter Baer Galvin, Greg Gagne 저/박민규 역 | 퍼스트북
각각의 프로세스는 독립된 메모리 공간을 가짐.
특정 프로세스만 접근할 수 있는 합법적인 메모리 주소 영역을 설정하고, 프로세스가 합법적인 영역만을 접근하도록 보호해야 함.
메모리 공간의 보호는 CPU 하드웨어가 사용자 모드에서 만들어진 모든 주소와 레지스터를 비교함으로써 이루어짐.
논리 주소 공간 구조
베이스와 상한 레지스터를 통한 주소 보호
프로그램이 실행되기 위해서는 메인 메모리에 적재되어 프로세스가 되어야 함
입력 큐(디스크에서 메인 메모리로 적재되기를 기다리고 있는 프로세스들의 집합)에서 하나의 프로세스를 선택해서 메모리에 적재 후 실행, 프로세스가 실행되는 동안 메모리에서 명령어와 자료를 엑세스
주소는 각 단계에서 다양하게 표현
명령어와 자료의 바인딩은 시점에 따라 다음과 같이 구분
논리 주소: CPU(프로그램)가 생성하는 주소
물리 주소: 메모리가 취급하게 되는 주소(즉, 메모리 주소 레지스터 MAR 에 주소지는 주소)
바인딩 기법
메모리 관리 장치(MMU)
사용자 프로그램은 논리 주소만을 다루고 실제적인 물리 주소를 결코 알 수 없음
→ 메모리 참조 시 실행시간 바인딩이 발생
동적 적재에서 각 루틴은 실제 호출되기 전까지는 메모리에 올라오지 않고 재배치 가능한 상태로 디스크에서 대기
장점
동적 적재는 운영체제로부터 특별한 지원을 필요로 하지 않음
동적 연결을 지원하지 않으면 모든 시스템 라이브러리를 호출하는 프로그램들은 그들의 이진 프로그램 이미지 내에 시스템 라이브러리 루틴들을 한 부씩 가지고 있어야 함
내부 동작 루틴
프로세스는 실행 도중에 임시로 보조 메모리(디스크)로 보내졌다가 다시 메모리로 되돌아올 수 있으며, 이를 스와핑이라 한다,
스와핑은 우선순위 기반 스케줄링 알고리즘에 적용될 수 있음
스왑 시간의 대부분이 디스크 전송 시간 → 전송 시간은 스왑될 메모리의 크기와 비례
메모리는 일반적으로 운영체제와 사용자 프로세스들, 두 개의 부분으로 분할
연속 메모리 할당 시스템에서 각 프로세스는 연속된 메모리 공간을 차지한다.
사용 가능한 메모리 블록인 공간(hole)의 크기가 다양하며(가변 분할) 메모리에 분산되어 있음
새 프로세스가 도착하면 이를 수용할 수 있는 충분한 크기의 공간을 할당
운영체제는 할당된 분할과 가용한 분할(hole)에 관한 정보를 유지해야 함
일련의 가용 공간-리스트로부터 크기 n-바이트 블록을 요구하는 것을 어떻게 만족시켜 줄 것이냐를 결정하는 문제
단편화는 공간 중 일부가 사용 못하게 되는 것을 말함
외부 단편화는 압축을 하여 해결 가능
메모리의 모든 내용들을 한군데로 몰고 모든 자유 공간들을 다른 한 군데로 몰아서 큰 블록을 생성
압축은 프로세스들의 재배치가 실행 시간에 동적으로 이루어지는 경우에만 가능
사용자 관점에서 지원되는 메모리 관리 방식
프로그램은 세그먼트의 집합이며, 세그먼트는 다음과 같은 것들의 논리적 단위이다.
주 프로그램(main())
프로시저
함수
메서드
객체
광역 변수, 지역 변수
스택
심볼 테이블, 배열
논리주소는 <segment-number, offset(상대값)> 두 부분으로 구성
사용자가 정의한 이차원 주소를 일차원의 실제 주소로 사상하는데에 세그먼트 테이블을 사용
테이블의 각 항목은
페이징은 논리 주소 공간이 연속적인 공간에 모여 있어야 한다는 제약을 제거
CPU에 의해 생성된 주소는 두 부분으로 분할
Ex) 논리 주소 공간의 크기가 2^m이고, 페이지의 크기가 2^n이라면…
→ 논리 주소의 상위 m-n 비트는 페이지 번호를 나타내고, 하위 n 비트는 페이지 변위를 나타냄
페이지가 2048 B이고 프로세스가 72,766 B를 요구한다면?
페이지 크기 = 2048 바이트
프로세스 크기 = 72766 바이트
= 35 페이지 + 1086 바이트
36 번째로 할당되는 페이지 프레임은 2048 - 1086 =962 바이트의 내부 단편화가 발생
페이지 테이블은 메인 메모리에 저장(프로세스마다 페이지 테이블을 가짐)
매 데이터/명령 접근을 위해 두 번의 메모리 액세스를 요구
물리 주소에서 페이지 테이블 참조 → 페이지 테이블에서 데이터/명령 참조
(*페이지 테이블도 메모리이다)
두 번의 메모리 접근 문제는 TLB라고 불리는 특수한 소형 하드웨어 캐시(캐시 메모리) 를 사용하여 해결
페이지 번호가 TLB에서 반복되는 비율을 적중률이라 한다.
TLB 탐색 20 ns, 메모리 접근 100 ns, TLB 적중률 80%일때 실제 메모리 접근시간은?
= 적중률메모리 접근 + (1-적중률) (2*메모리접근)
= 0.8100+0.22*100
= 120ns
메모리 보호는 각 페이지에 붙어 있는 보호 비트에 의해 구현
페이지 테이블의 각 항목에는 유효/무효 비트 추가
페이징의 또 다른 장점은 코드를 쉽게 공유할 수 있다는 점이다.
재진입 가능 코드(reentrant code)라면 공유가 가능
공유되는 프로그램: 문서 편집기, 컴파일러, 윈도우 시스템, 실시간 라이브러리, 데이터베이스 시스템
💡 페이징은 메모리를 ‘페이지’라는 고정된 크기로 분할하고, 세그먼테이션은 논리적인 의미를 가지는 단위(함수, 데이터, 메인 등)로 분할한다. 즉, 세그먼트는 크기가 다르다.
현대 컴퓨터는 매우 큰 주소 공간을 가진다. 이러한 환경에서는 페이지 테이블도 상당히 커진다.
페이지 테이블을 구성하는 일반적인 방법들을 소개한다.
논리 주소 공간을 여러 단계의 페이지 테이블로 분할
: 페이지 테이블 자체가 다시 페이징
Ex) 32비트 논리주소 공간, 4KB(2^12) 크기의 페이지 일 때…
20비트 페이지 번호와 12비트 페이지 변위로 나누어짐
페이지 테이블도 페이지화되면서 페이지 번호를 10 비트씩 분할
64비트 논리 주소 공간을 가진 시스템에서는 2 단계 페이징 기법이 적절하지 못함
→ 두 번째 바깥 페이지를 도입한 3 단계 페이지 테이블 구성
주소 공간이 32 비트보다 커지면서 해시형 페이지 테이블을 사용함
가상 페이지 번호가 해시 값이 되어 페이지 테이블을 참조
같은 위치로 해시되는 충돌인 경우를 위해 각 항목은 연결 리스트로 구성
해시형 페이지 테이블의 동작
지금까지의 페이지 테이블은 페이지 마다 하나의 항목을 가짐
→ 페이지 테이블 크기가 커짐
역 페이지 테이블
현재 가장 널리 사용되는 cpu칩
세그먼테이션과 페이지화 된 세그먼테이션을 모두 지원
(s=세그먼트 번호, g=세그먼트가 GDT인지 LDT인지를 표시, P=보호와 관련된 정보 표시)
CPU가 논리 주소 생성 → 세그먼트 유닛은 각 논리 주소를 32비트 선형 주소로 변환
→ 페이징 유닛이 선형 주소를 메인 메모리의 물리 주소로 변환(페이지 크기는 4KB 또는 4MB)
2 단계 페이징 기법 사용
💡 페이지 크기가 작으면 테이블의 항목이 많아지므로 페이지 테이블의 크기가 커진다. 반비례 관계이다.
9장의 흐름…
주소가 런타임에 결정되면 프로그램 내 주소와 실제 주소가 다르다.
논리주소(가상 주소) → 물리주소 변환하는 하드웨어는 MMU
메모리에 적재하는 방법은 세그먼테이션(논리적 의미, 크기가 다름) 또는 페이징(동일한 크기)
TLB