들어가기 앞서 .. 복습 !
논리적 주소 vs 물리적 주소
논리적 주소(가상 주소)
- 프로세스마다 독립적으로 가지는 주소 공간
- 각 프로세스마다 0번지부터 시작
- CPU가 보는 주소는 논리적 주소이다.
물리적 주소
- 메모리에 실제로 올라가는 위치
- 보통 메모리의 낮은 주소 영역에는 운영체제가 올라가고, 높은 주소 영역에는 사용자 프로세스가 올라간다.
Address Binding (주소 바인딩)
어떤 프로그램이 메모리의 어느 위치에 즉, 어떤 물리적 주소에 load 될지를 결정하는 과정이다.
즉, 프로세스의 논리적 주소를 물리적 메모리 주소로 연결하는 작업을 말한다.
이는 binding하는 시점에 따라 분류된다.
Symbolic Address → Logical Address → Address Binding → Physical Address
Symbolic Address는 프로그래머 입장에서 사용하는 것으로 변수 이름과 같은 형태의 주소를 말한다.
Compile Time Binding(컴파일 타임 바인딩)
프로세스의 물리적 주소가 컴파일 때 정해진다.
프로세스가 메모리의 어느 위치에 들어갈지 미리 알고있다면 컴파일러가 절대 주소(Absolute address) 즉, 고정된 주소를 생성한다.
따라서 만약 위치가 변경된다면 재컴파일을 해주어야한다.
컴파일 타임 주소 할당은 프로세스 내부에서 사용하는 논리적 주소와 물리적 주소가 동일하다.
컴파일 타임 주소 할당의 문제점은, 주소가 고정되어 있기 때문에
메모리 상에 빈 공간이 많이 발생할 수 있어 비효율적이고, 로드하려는 위치에 이미 다른 프로세스가 존재할 수 있다.
Load Time Binding(로드 타임 바인딩)
프로세스가 메모리의 어느 위치에 들어갈지 미리 알 수 없다면, 컴파일러는 Relocatable code를 생성해야 한다.
Relocatable code(재배치 코드)는 메모리의 어느 위치에서나 수행될 수 있는 기계 언어 코드이다.
그리고 Loader가 프로스세를 메모리에 load하는 시점에 물리적 주소를 결정한다.
따라서 로드 타임 주소 할당은 논리적 주소와 물리적 주소가 다르다.
하지만, 프로세스 내에 메모리를 참조하는 명령어들이 많아서 이들의 주소를 다 바꿔줘야 하기 때문에, 로딩할 때 시간이 매우 커질 수 있다는 단점이 있다.
따라서 컴파일 타임과 로드 타임 주소 할당은 실제로 잘 쓰이지 않는다.
Execution Time or Runtime Binding(실행 시간 바인딩)
프로세스가 수행이 시작된 이후에도 프로그램이 위치한 물리적 메모리 위치를 변경할 수 있는 바인딩 방식이다.
즉, 런타임때 물리적 주소가 결정되며 도중에 주소가 바뀔 수 있다.
CPU가 주소를 참조할 때 마다 address mapping table을 이용하여 binding을 점검한다.
런타임 주소 할당은 MMU(Memory Management Unit)라는 하드웨어 장치를 사용해 논리적 주소 → 물리적 주소로 바꿔준다.
base register, limit register 등과 같은 하드웨어적인 자원이 필요하다.
프로세스가 CPU에서 수행되면서 생성해내는 모든 주소값에 대해 base register의 값을 더해주어 물리적 주소를 생성하는 방식이다.
base register는 하나이므로 프로세스끼리 공유한다.
base register(Relocation Register) - 접근할 수 있는 물리적 주소의 최솟값
limit register - 프로그램의 크기 즉, 논리적 주소의 범위로 잘못된 메모리를 참조하지 않도록 막아주는 기능을 한다.
MMU (Memory Management Unit)
논리적 주소 → 물리적 주소로 매핑해주는 하드웨어 장치
CPU에서 수행되는 사용자 프로세스가 생성해내는 모든 주소 값에 대해 기준 레지스터의 값을 더하는 방식을 말한다.
MMU 기법에서 사용자 프로그램이나 CPU는 논리적 주소만을 다룰 뿐, 실제 메모리 주소는 알지 못하고 알 필요도 없다.
MMU 동작 기법
CPU가 논리적 메모리 346번지에 있는 내용을 달라고 하면 MMU는 2개의 레지스터를 가지고 변환을 한다.
실제 물리적 메모리의 시작 위치와 논리적 메모리 주소(offset 개념)를 더한 값을 CPU에게 전달한다.
CPU가 요청한 논리적 주소값을 한계 레지스터와 비교하여 범위를 넘어서면 trap을 발생시켜 프로세스를 강제 종료한다.
그렇지 않으면 기준 레지스터(재배치 레지스터)의 값을 더해서 물리적 주소로 변환한다.
💡 주의해야할 점
커널 모드의 경우 MMU가 물리적인 주소로 변환하지 않고 논리적 주소를 그대로 사용한다.
따라서 커널 모드인지 체크하는 과정이 포함된다.
메모리 기법 관련 용어
Dynamic Loading (동적 로딩)
메모리 공간의 효율적 이용을 위해 메모리에 프로세스 전체를 미리 올리는 것이 아니라 해당 루틴이 호출될 때 메모리에 load하는 것이다.
각 루틴이 호출되기 전까지는 메모리에 적재되지 않고 재배치 가능한 상태로 디스크에서 대기하고 있다.
먼저 main 프로그램이 메모리에 올라와 실행된다. 다른 루틴을 호출하게 되면 루틴이 메모리에 적재됐는지 조사하고 적재되어 있지 않다면 재배치 가능 연결 적재기(relocatable linking loader)가 실행되며 요구된 루틴을 메모리고 가져오고, 이러한 변화를 테이블에 기록해준다.
이후 CPU 제어는 중단되었던 루틴으로 보내진다.
Dynamic Linking(동적 연결)
연결(linking)이란 프로그래머가 작성한 소스코드를 컴파일하여 생성된 목적 파일(object file)과 이미 컴파일된 라이브러리 파일들을 묶어 하나의 실행 파일을 생성하는 과정이다.
동적 연결은 컴파일을 통해 생성된 목적 파일과 라이브러리 파일 사이의 연결을 프로그램의 실행 시점까지 지연하는 기법이다.
이는 주로 표준 C언어 라이브러리와 같은 시스템 라이브러리에 사용된다.
이러한 기능이 없다면 시스템의 각 프로그램은 실행 가능 이미지에 해당 언어 라이브러리의 사본을 포함해야 한다.
정적 연결 vs 동적 연결
정적 연결
라이브러리가 프로그램의 실행 파일 코드에 포함되어 실행 파일의 크기가 커진다.
동일한 라이브러리를 각각의 프로세스가 메모리에 올리므로 메모리 낭비가 심하다.
동적 연결
실행 파일에 라이브러리 코드가 포함되지 않으며 프로그램이 실행되면 라이브러리 함수를 호출할 때가 되어서야 라이브러리에 대한 연결이 이루어진다.
라이브러리 호출 부분에 라이브러리 루틴의 위치를 찾기 위한 stub이라는 작은 코드를 둔다.
라이브러리가 이미 메모리에 있으면 그 루틴의 주소로 가고 없으면 디스크에서 읽어온다.
운영체제의 도움이 필요하다.
Overlap(오버랩)
메모리에 프로세스에서 실제 필요한 정보만을 올리는 기법
물리적 메모리의 크기 제약으로 인해 하나의 프로세스 조차도 메모리에 한꺼번에 올릴 수 없었을 때, 프로세스의 주소 공간을 분할해서 당장 필요한 일부분을 메모리에 올려 실행하고 해당 부분에 대한 실행이 끝난 후에 나머지 부분을 올려 실행하는 기법을 뜻한다.
프로세스의 크기 > 메모리의 크기 일 때 유용하다
참고
'CS > 운영체제' 카테고리의 다른 글
[운영체제] 고정 분할 방식과 가변 분할 방식의 메모리 관리 (0) | 2022.07.07 |
---|---|
[운영체제] 페이지 교체 알고리즘 (0) | 2022.07.07 |
[운영체제] 내부 단편화 vs 외부 단편화 (0) | 2022.07.07 |
[운영체제] 페이징과 세그멘테이션 (0) | 2022.07.07 |
[운영체제] 세마포어(Semaphore) & 뮤텍스(Mutex) (0) | 2022.04.04 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!