메모리 주소
1byte로 나뉜 메모리의 각 영역은 메모리 주소로 구분. 보통 0번지부터 시작
CPU는 RAM에 있는 내용을 가져오거나 작업 결과를 저장하기 위해 주소를 사용해서 기억함.
시분할 시스템을 사용하면서 OS를 포함한 모든 응용 프로그램이 RAM에 올라와 실행되어 메모리 관리가 복잡해짐
프로세스 입장은 자기 혼자 RAM을 다 쓰려하고, 메모리 관리하는 입장에선 효율적으로 나눠서 관리하고 싶어함
그 효율적으로 나눠서 관리하기 위한 방법으로
OS 내 각 프로세스가 분리된 메모리 공간을 가지게 함.
PCB에 경계 레지스터와 한계 레지스터로 쓸 수 있는 메모리 공간의 한계를 둠.
*경계 레지스터: 메모리 공간 시작주소
*한계 레지스터: 메모리 공간 크기
ex) 시작 주소: 30번지, 끝 주소 70번지면 경계 : 30, 한계 : 40
다른 프로세스가 다른 프로세스의 메모리 공간에 침입할 수 없게 함.
소스코드 번역과 실행
언어 번역 프로그램 종류
컴파일러 : 소스 코드 전체를 컴퓨터가 실행할 수 있는 기계어로 번역한 후에 한번에 실행.
소스코드 -> 컴파일러 -> 기계어 -> CPU(실행)
인터프리터 : 소스코드를 한 행씩 번역하여 실행함
소스코드 -> 인터프리터(바로 번역, 실행) -> CPU
컴파일러 방식의 목적
- 오류 발견 : 소스코드에서 오류를 발견하여 실행 시 문제가 없도록 하는 것
- 소스코드 최적화 : 소스코드를 간결하게 정리하여 실행 속도를 빠르게 하는 것
분할 컴파일(다시 보기)
변수와 메모리 할당
변수마다 메모리 할당의 크기가 다 다름
컴파일러는 변수에 대해 메모리 공간을 확보하고 에러를 찾기 위해 심볼 테이블을 유지함.
* 심볼 테이블 : 컴파일러 또는 인터프리터같은 언어 변환기(프로그램의 소스코드의 각 식별자가 자신의 선언 또는 소스에서의 외형과 관련된 정보와 연관되는)에서 사용되는 데이터 구조
컴파일러가 변수를 쓸 때마다 사용 범위를 넘는지 점검한다(지역변수인지)
변수들을 메모리 주소로 바꾸어서 기계어(어셈블리어)로 된 실행 파일을 만든다.
이 때 변수 주소는 논리 주소이다.
*논리 주소 : 물리 주소는 절대적으로 RAM 시작점인 0부터 시작해서 주소 계산을 한다면,
논리 주소는 다른 프로그램 끝 주소에서부터 0으로 시작(상대적)해서 주소를 계산한다.
오류 등을 검출해 내기에 논리 주소가 더 유리하다.(시작점을 명확하게 알 수 있음)
논리 주소와 물리주소
보통 메모리를 운영체제 영역과 사용자 영역으로 나누어서 관리한다.
사용자 프로세스가 OS 크기에 따라 매번 적재되는 주소가 달라지는 건 번거로워서,
user process를 메모리 최상위부터 사용한다.
but 메모리를 거꾸로 쓰기 위해 주소를 변경하는 게 복잡하기 때문에 잘 안쓰인다.
그래서 나온게 경계 레지스터이다. 정확히는 OS 영역과 user 영역 경계 지점의 주소를 나타내었다.
(그래서 시작점이라고 표현했다.)
CPU 내에 있는 경계 레지스터가 user 영역이 OS 영역으로 침범하는 걸 막아준다.
관리자는 user가 작업을 요청할 때마다 경계 레지스터 값을 벗어나는 작업을 요청하는 프로세스가 있으면
그 프로세스를 종료시켜 버린다.
물리 주소 공간(physical address space)
하드웨어 입장에서 바라본 주소 공간으로 컴퓨터마다 크기가 다름
프로그램이 메모리에 저장되는 실제적인 공간
메모리가 취급하는 주소
논리 주소 공간 (logical address space)
user 입장에서 본 주소공간
다중 프로세스들이 공간을 쉽게 사용하기 위해 사용
CPU가 취급하는 주소
MMU( Memory Management Unit)
논리 주소와 물리주소를 변환해주는 기능을 수행한다.
메모리 관리 작업
메모리 가져오기(fetch)
실행할 프로세스와 데이터를 RAM으로 가져옴
필요로 하는 데이터를 언제 가져올지 결정하는 정책(스케줄링)
메모리 배치(placement)
가져온 프로세스와 데이터를 메모리 어디에, 위치에 올려놓을 지 결정(공간 할당)
메모리를 같은 크기로 자를건지 프로세스 크기에 맞게 자를 건지 결정
메모리 재배치(replacement)
꽉 찬 메모리를 정리하고 새 프로세스 데려오기 위해 오래된 프로세스를 내보냄
메모리가 꽉 차면 정리하기 위해 내보낼 프로세스를 결정함.
컴퓨터가 32bit CPU면
한 번에 다룰 수 있는 최대 데이터의 크기.
CPU 내 레지스터 크기도 전부 32bit, ALU와 대역폭도 32bit
메모리 주소 크기 : 2의 32승 바이트 : 약 4GB
메모리 오버레이(memory overlay)
프로그램 크기가 실제 메모리보다 클 때
전체 프로그램을 메모리에 가져오는 것 대신 적당하게 잘라서 가져오는 것을 말함.
-한정된 RAM에서 RAM보다 큰 프로그램을 실행할 수 있다.
-프로그램 전체가 아닌 일부만 올려놔도 실행이 가능하다.
작동 방식
- 프로그램이 실행되면 필요한 모듈만 메모리에 올라와 실행된다.
이 때 자르고 남은 것은 스왑 영역(swap area)에 모아놓는다.
저장장치는 장소만 빌려주고 메모리 관리자가 관리하는 방식으로,
사용자는 실제 메모리와 스왑 영역의 크기를 합쳐서 전체 메모리로 인식하고 사용한다.
***
swap in : 스왑 영역에서 메모리로 데이터를 가져오는 작업
swap out: 다시 스왑 영역으로 데이터를 내보내는 작업
메모리 할당
프로세스에게 물리 메모리를 할당하는 것
연속 메모리 할당 : 프로세스가 할당받은 메모리가 덩어리로(연속되게) 할당
비연속 메모리 할당 : 프로세스가 할당받은 메모리 공간을 여러 덩어리(여러 모듈로 쪼개서)할당
여러 프로세스를 배치하는 방법
고정 분할(paging, 페이징 메모리 관리 기법) : 프로세스 크기 상관없이 같은 크기로 메모리를 나눔
- 프로세스 크기 상관없이 똑같이 메모리들을 나눈다.
- 각 메모리 조각에 프로세스를 배치하고 약간의 공간이 남는걸 내부 단편화(internal fragmentation)라고 한다.
- 큰 프로세스가 메모리에 올라오면 여러 조각으로 나누어서 배치된다.
- 메모리를 일정하게 나눠서 관리하므로 메모리 관리가 수월해진다.
- 쓸모없는 공간이 자꾸 생겨 메모리 낭비를 유발한다.
가변 분할(segmentation, 세그먼테이션 메모리 관리 기법) : 프로세스 크기 따라 메모리를 나눔
- 프로세스 크기에 맞게 메모리가 분할됨
- 메모리 영역이 각각 달라지게 된다.
- 프로세스들이 메모리에 할당되어서 작업하다 종료되면 빈 공간들이 생기는데,
이것을 단편화(fragmentation)라고 한다.
가변 분할 방식에서는 이러한 단편화를 외부 단편화(external fragmentation) 라고 한다.
이것을 해결하기 위해 메모리 배치 방식(memory placement strategy)이나 조각모음을 사용함.
* 메모리 배치 방식 : 작은 조각이 발생하지 않도록 프로세스를 배치하는 것
조각 모음 : 작은 조각을 모아 하나의 큰 덩어리로 만드는 작업
- 프로세스를 한 덩어리로 처리하여, 하나의 프로세스를 연속된 공간에 배치한다.
- 빈 공간을 하나로 합쳐야 하고, 이 때문에 다른 프로세스 자리도 옮겨야 해서 메모리 관리가 좀 복잡하다.
최초 배치 : 다 확인하지 않고 첫 번째로 발견한 곳부터 배치하는 방법
최적 배치 : 빈 공간 모두 확인한 후 들어갈 수 있는 크기 중 가장 작은 공간에 효율적으로 배치하는 방법
최악 배치 : 빈공간 모두 확인한 후 들어갈 수 있는 크기 중 가장 큰 공간에 배치
조각 모음: (defragmentation)
서로 떨어져있는 여러 빈 공간을 하나로 합치는 작업
버디 시스템
가변 분할 방식의 외부 단편화를 완화, 가변과 고정의 중간 구조
1. 프로세스 크기에 맞게 메모리를 반 자르고(이걸 효율적이게 될 때까지 반복) 프로세스를 메모리에 배치함
2. 쪼개진 메모리 각 구역에 프로세스 하나만 들어감
3. 프로세스가 종료되면 주변 빈 조각과 합쳐서 하나의 큰 덩어리를 만든다.
-가변 방식처럼 메모리가 프로세스 크기대로 나뉘게 됨
-고정 방식처럼 하나의 구역에 다른 프로세스가 못 들어가고, 메모리 한 구역 내부에 내부 단편화가 발생한다.
but 비슷한 크기 조각이 서로 모여 작은 조각을 통합해 큰 조각을 만들기가 더 쉬워진다.
'코딩공부' 카테고리의 다른 글
가상 메모리 (0) | 2025.05.13 |
---|---|
프로세스 메모리 구조, Program Counter, NULL, Garbage Collector, Stack Overflow (0) | 2025.05.05 |
정규표현식, XML과 JSON, Tokenizer, Lexer, Parser, AST (2) | 2025.04.29 |
코틀린으로 서버 대기열 구축하기 (0) | 2025.04.18 |
코틀린 배열, 제너릭, 클래스와 생성자, 스택과 (0) | 2025.04.15 |