프로그램을 메모리에 올리기
- 메모리 구조
- 주소(Address) + 데이터(Data)
- 프로그램 개발
- Source file : 고수준 언어
- Object file : 컴파일 또는 어셈블 결과
- Excutable file : 링크 결과
- 컴파일러, 어셈블러, 링커, 로더
- 컴파일러 : Source file을 Object file로
- 링커 : Object file과 라이브러리를 결합하여 실행 파일 생성
- loader : 실행 파일을 메모리에 적제
- 프로그램 실행
- 프로그램의 실행을 위해서는 3가지가 메모리에 들어간다
- code + data + stack
- code는 기계어 즉 코드
- data는 data
- stack
- 실행 파일을 메모리에 올리기
- 메모리의 어느 주소에 올릴 것인가?
- loader가 결정한다
- 적재 시 매번 물리적인 주소는 달라진다
- 멀티 프로그래밍 환경에서 다른 프로그램도 게속 올라오고 내려간다
- 메모리 환경이 게속 달라짐
- CPU는 MMU 참조하여 일관적으로 접근 가능, MMU 사용하여 mapping
- CPU는 Memory Menagement Unit을 경유하여 메모리에 접근
- MMU에 프로세스가 메모리에 저장되있는 시작 주소를 넣는다
- CPU 입장에서는 그냥 주소 참조, 실제로는 시작 주소 + 주소
- CPU가 3을 조회, MMU의 시작 주소가 5면 실제로는 8 조회
- MMU는 애플리케이션이 악의적으로 다른 영역을 접근하도록 하는 것도 막는다
- 메모리의 어느 주소에 올릴 것인가?
메모리 적재 방법
Dynamic Loading
- 프로그램 실행에 반드시 필요한 루틴/데이터만 적재한다
- 모든 루틴이 다 사용되는 것은 아니다(ex: 오류 처리)
- 모든 데이터가 다 사용되는 것은 아니다(ex: 배열)
- 자바 : 모든 클래스가 다 사용되는 것은 아니다(class loader)
- 실행 시 필요하면 그때 해당 부분을 메모리에 올린다
Dynamic Linking
- 여러 프로그램에 공통 사용되는 라이브러리
- 공통 라이브러리 루틴를 메모리에 중복으로 올리는 것은 낭비
- 라이브러리 루틴 연결을 실행 시까지 미룬다
- 오직 하나의 라이브러리 루틴만 메모리에 적재되고
- 다른 애플리케이션 실행 시 이 루틴만 연결된다
- 리눅스에서는 공유 라이브러리, 윈도우에서는 동적 연결 라이브러리
Swapping
- 메모리에 적재되어 있으나 현재 사용되지 않고 있는 프로세스 이미지
- 메모리 활용도 높이기 위해 swap device(하드 디스크) 로 몰아내기
- swap-out, swap-in
- Relocation register 사용으로 적재 위치는 무관
- 메인 메모리에는 Relocation register을 통해 접근한다
- 프로세스 크기가 크면 backing store 입출력에 따른 부담이 크다
- 메모리 활용도 높이기 위해 swap device(하드 디스크) 로 몰아내기
연속 메모리 할당
프로세스를 연속된 메모리 공간에 통째로 할당하는 방식
외부 단편화가 일어날 수 있다
외부 단편화
- whole : 메모리에 있는 빈 공간
- 외부 단편화란 공간은 충분하나 whole 이 연속되지 않아 프로세스 적재를 할 수 없는 것
- 프로세스가 연속해서 할당되더라도 반납되고 새로 할당되고 반복되면 프로세스 사이에 빈 공간이 생긴다
연속 메모리 할당 방식
- First fit
- whole 에 순차적으로 적재하는 방식
- 연산이 필요 없어 속도는 빠르다
- Worst fit
- 가장 크기의 차이가 큰 whole에 적재하는 방식
- 비교적 메모리 이용률이 높았다
- best fit
- 프로세스와 가장 크기가 비슷한 whole에 적재
- 비교적 메모리 이용률이 높았다
셋 중 어떤 방식을 사용하더라도 전체 메모리의 1/3은 사용하지 못한다.
그래서 나온 방식이 compaction
- compaction
- 프로세스의 메모리를 정리해서 whole을 한곳으로 모으는 것
- 최적 알고리즘은 존재하지 않는다
- 계산할 것이 많다
- 부담이 많다
가변 메모리 할당
페이징
프로세스를 일정한 단위로 분할하여 메모리에 적재하는 방식
- 프로세스는 페이지(page)의 집합
- 메모리는 프레임(frame)의 집합
페이지를 프레임에 할당
- MMU 내의 재배치 레지스터 값을 바꿈으로서
- CPU는 프로세스가 연속된 메모리 공간에 위치한다고 착각
- MMU안에 relocation register를 여러 개 두고 CPU는 MMU를 통해 메모리에 접근한다.
- 때문에 CPU입장에서는 프로세스가 연속되어 있다.
- 이러한 MMU는 페이지 테이블(page table)이 된다
외부 단편화는 없지만, 일정한 크기로 분할하기 때문에 내부 단편화가 일어난다.
- 내부 단편화
- 프로세스 크기가 페이지 크기의 배수가 아니라면
- 마지막 페이지는 한 프레임을 다 채울 수 없다
- 남은 공간은 메모리 낭비로 이어진다
- 외부 단편화에 비해서는 미미하다
주소 변환
cpu는 논리 주소로 메모리에 접근하게 되고, 페이지 테이블이 이런 논리 주소를 물리 주로로 변환하여 준다
- 논리 주소(Logical address)
- CPU가 내는 주소는 2진수로 표현
- 하이 n 비트는 offset
- 상위 m-n비트는 페이지 번호
- 주소 변환 : 논리주소 -> 물리주소
- 페이지 번호(p)는 페이지 테이블 인덱스 값
- p에 해당되는 테이블 내용이 프레임 번호(l)
- 변위(d)는 변하지 않음
- 페이지 번호(p)는 페이지 테이블 인덱스 값
보호와 공유
- 보호 : 해킹 등 방지
- 모든 주소는 페이지 테이블을 경유하므로
- 페이지 테이블 엔트리마다 r, w, x 비트 두어
- read, write, execute
- 해당 페이지에 대한 접근 제어 가능
- 공유 : 메모리 낭비 방지
- 같은 프로그램을 쓰는 복수 개의 프로세스가 있다면
- ex) 아래한글 여러 개 실행
- code + stack + data 에서 code는 공유 가능
- 프로세스의 페이지 테이블 코드 영역이 같은 곳을 가리키게 한다
- 물론 한 프로세스가 코드를 변경하면 안된다
- 이것을 non-self modifying code 라 한다
- 컴퓨터 용어로는 pure code 라 한다
- 같은 프로그램을 쓰는 복수 개의 프로세스가 있다면
세그멘테이션
프로세스를 논리적인 단위(세그먼트)로 분할하여 메모리에 적재하는 방식
프로세스는 세그먼트의 집합
세그먼트의 크기는 일반적으로 같지 않다
세그먼트를 메모리에 할당
- MMU 내의 재배치 레지스터 값을 바꿈으로서
- CPU는 프로세스가 연속된 메모리 공간에 위치한다고 착각
주소 변환(Address Translation)
- 논리주소(Logical address)
- CPU가 내는 주소는 segment 번호(s) + 변위(d)
- 주소변환: 논리주소 -> 물리주소
- 세그먼트 테이블 내용 : base + limit
- 세그먼트 번호(s)는 세그먼트 테이블 인덱스 값
- s에 해당되는 테이블 내용으로 시작 위치 및 한계값 파악
- 한계(limit)를 넘어서면 segment violation 예외 상황 처리
- 물리주소 =
base[s] + d
보호와 공유
- 보호
- 모든 주소는 세그먼트 테이블을 공유하므로
- 세그먼트 테이블 엔트리마다 r, w, x 비트 두어
- 해당 세그먼트에 대한 접근 제어 가능
- limit를 통해 접근 제한
- 공유 : 메모리 낭비 방지
- 같은 프로그램을 쓰는 복수 개의 프로세스가 있다면
- ex) 아래한글 여러 개 실행
- code + stack + data 에서 code는 공유 가능
- 프로세스의 세그먼트 테이블 코드 영역이 같은 곳을 가리키게 한다
- 물론 한 프로세스가 코드를 변경하면 안된다
- 이것을 non-self modifying code 라 한다
- 컴퓨터 용어로는 pure code 라 한다
- 같은 프로그램을 쓰는 복수 개의 프로세스가 있다면
페이징과 세그멘테이션
세그멘테이션은 의미 있는 단위로 자르기 때문에 페이징보다 보호와 공유 측면에서 더 나은 방법이다
- 페이징은 일관적으로 자르다 보니 논리적으로 상관 없는 데이터가 묶일 수 있다
- 코드와 데이터가 같은 프레임에 있다면 코드 실행 시 데이터에는 접근하면 안되지만
- 페이지 테이블에서 막기가 곤란하다
- 관계있는 세그먼트가 묶여 있기 때문에 공유하기도 좋다
- 페이징은 일관적으로 자르다 보니 논리적으로 상관 없는 데이터가 묶일 수 있다
세그멘테이션은 외부 단편화가 발생할 수 있다
- 세그먼트 크기는 고정이 아니라 가변적
- 크기가 다른 각 세그먼트를 메모리에 두려면 동적 메모리 할당을 해야 한다
세그멘테이션 + 페이징
- 세그멘테이션은 보호와 공유면에서 효과적
- 페이징은 외부 단편화 문제를 해결
- 따라서 세그먼트를 페이징하자!?!?
- CPU - 세그먼트 테이블 - 페이지 테이블 - 메모리
- 주소 변환 과정을 여러 번 거쳐야 하므로 부담
'CS > 운영체제' 카테고리의 다른 글
blocking, non-blocking, Sync, Async (0) | 2022.08.27 |
---|---|
가상 메모리 (0) | 2022.08.14 |
Deadlock (0) | 2022.08.04 |
프로세스 동기화 (0) | 2022.07.29 |
CPU Scheduling (0) | 2022.07.24 |