메모리 관리

메모리 관리의 복잡성을 해결하는 방법

메모리 관리의 복잡성

메모리 구조는 1B 크기로 나눈다.

보통 나눠진 영역은 메모리 주소로 구분하는데 보통 0번지 부터 시작된다.

CPU는 메모리에 있는 내용을 가져오거나 작업 결과를 메모리에 저장하기 위해 메모리 주소 레지스터를 사용한다.

메모리 주소 레지스터에 필요한 메모리 주소를 넣으면 데이터를 메모리에서 가져오거나 메모리에 데이터를 옮길 수 있다

소스코드의 번역과 실행

보통 컴파일러를 사용하여 작성한 프로그램을 실행 가능한 코드로 변경한다.

기계어와 어셈블리어는 컴퓨터의 동작을 가장 직접적으로 표현한 언어로 저급 언어라고 한다

저급언어와 반대되는 이해하기 쉬운 언어는 C언어와 자바가 있다

🔴 컴파일러 : 소스코드를 컴퓨터가 실행할 수 있는 기계어로 번역한 후 한꺼번에 실행한다

🟠 인터프리터 : 소스코드를 한 행씩 번역하여 실행한다

컴파일러의 목적

  • 오류 발견

소스 코드의 오류를 발견하여 실행 시 문제를 사전에 찾아낸다.

오류를 찾기 전 심벌 테이블을 사용하는데 변수 선언부에 명시한 변수의 이름과 종류를 모아놓은 테이블이다

  • 코드 최적화

컴파일러는 실행하기 전 코드를 점검하여, 중복되거나 사용하지 않는 코드를 검출한다.

컴파일러는 오류와 중복을 점검하고 최적화 하는 목적을 가진다

컴파일 과정

작성한 소스코드를 목적 코드로 변환한 후 실행파일을 만든다

I) 소스코드 작성 및 컴파일 
c언어나 자바로 코드를 작성하여 컴파일하면 목적코드가 만들어진다.
II) 목적코드와 라이브러리 연결 
목적코드가 만들어지면 라이브러리에 있는 코드를 목적 코드에 삽입하여 최종 실행 파일을 만든다. 
라이브러리는 자주 사용하는 함수를 시스템내에 만들어둔 것으로 작성이 까다롭고 귀찮은 함수를 모아 놓은 것이다
III) 동적 라이브러리를 포함하여 최종 실행
동적 라이브러리 방식은 함수가 변경되어도 새로 컴파일할 필요가 없다

메모리 관리자의 역할

매모리 관리 유닛(MMU) 라는 하드웨어를 통칭한다.

🔴 가져오기

사용자의 요청이 들어온 프로세스와 데이터를 메모리로 가져오는 작업이다.

앞으로 필요할 것으로 예상되는 데이터도 미리 가져오기도 한다

🟠 배치 작업

프로세스 데이터를 어디에 올려 놓을지 결정하는 작업이다

메모리를 어떤 크기로 자를 것인지가 가장 중요하다.

🟡 재배치 작업

새로운 프로세스를 가져와야 하는데 메모리가 꽉 찻다면 메모리에 있는 프로세스를 디스크로 옮겨 놓아야 새로운 프로세스 메모리를 가져올 수 있다

메모리 주소

CPU 32Bit 64Bit 차이

CPU의 비트는 한번에 다룰 수 있는 데이터의 최대 크기를 의미한다

32bit의 cpu의 내의 레지스터 크기는 전부 32bit이고 산술 논리연산 장치(ALU)도 32bit만 처리할 수 있도록 설계된다.

버스의 크기(대역폭)도 32bit이다

CPU의 비트는 메모리 주소 공간의 크기와도 연관이 잇다. 총23212^{32}-1개이며 약 4GB이다 CPU엔 메모리가 설치되어 있으며 각 메모리 주소 공간(물리 주소 공간)이 존재한다.

이와 반대로 사용자 입장에서 바라본 주소 공간은 논리 주소 공간이다

절대 주소와 상대 주소

메모리 관리자는 운영체제 영역과 사용자 영억으로 나누어 관리한다.

운영체제는 시스템을 관리하는 역할을 하기 때문에 사용자가 침범하지 못하도록 분리한다

사용자 프로세스는 운영체제 영역을 피하여 메모리에 올라간다.

사용자 영역이 운영체제 영역을 침범하는 것을 막으려면 하드웨어의 도움이 필요한데,

이는 CPU의 경계 레지스터가 담당한다.

메모리 관리자는 사용자 작업을 요청할 떄마다 경계 레지스터의 값을 벗어나는지 검사하고, 벗어난다면 종료시킨다

절대 주소

메모리 주소 레지스터가 사용하는 주소로, 컴퓨터의 램 실제 주소(물리 주소 공간)이다

상대 주소

프로세스 입장에서 운영체제의 메모리 위치와 상관없이,

주소공간이 항상 0번지 부터 시작되는 부분(논리 주소 공간)이다

상대 주소 => 절대 주소

사용자가 상대 주소의 데이터를 요청

메모리 관리자가 프로세스 데이터의 물리 주소 가져오라 명령

메모리 할당

단일 프로그래밍 환경

실제 메모리보다 큰 프로그램을 잘라서 가져오는 기법을 메모리 오버레이라고 한다

메모리 오버레이의 경우 프로그램을 몇 개의 모듈로 나누고, 필요시 모듈을 메모리에 가져와서 사용한다.

메모리 오버레이에서 모듈을 가져오거나 내보낼지는 프로그램 카운터가 결정한다.

스왑

메모리 모듈을 가져올때, 기존에 올라온 모듈을 보관하는 방법이다.

메모리가 모자라서 쫓겨난 프로세스는 저장장치의 스왑 영역에 저장되는데,

스왑영역에서 데이터를 가져오는 작업은 swap in, 스왑영역에서 데이터를 내보내는 작업을 swap out이라고 한다

최대 절전모드에서 데이터를 옮기는 곳도 스왑 영역이다

다중 프로그래밍 환경

메모리 분할 방식은 두가지 가변 분할, 고정 분할 방식이 존재한다

프로세스의 빈공간이 있어도 서로 떨어지면 작은 조각들이 발생하는데 단편화&조각화 라고한다

가변 분할

프로세스의 크기에 따라 메모리 분할 세그먼테이션 기법

한 프로세스가 연속된 공간에 배치되기 때문에 연속 메모리 할당

  • 최초 배치 : 단편화를 고려하지않는 것으로 메모리의 빈 공간에 배치할 때 적재 가능한 공간 찾고 첫 번째 공간에 배치한다

  • 최적 배치: 메모리의 빈 공간을 모두 확인한 후 적당한 크기중 가장 작은 공간에 배치한다

  • 최악 배치 : 가장 큰 공간에 프로세스를 배치하는 방법이다

어떤 방식을 사용해도 단편화 현상을 발생한다.

단편화가 발생하면 조각 모음을 통해 배치된 프로세스를 옮겨 빈 공간들을 추려낸다

고정 분할

메모리 조각에 프로세스를 배치하고 공간이 남는 현상을 내부 단편화 라고한다

가상 메모리 시스템에서는 고정 분할 방식을 페이징 이라고도 한다

프로세스 크기와 상관없이 메모리를 같은 크기로 나누는 것이다

비연속 메모리 할당이라고 한다

버디 시스템

프로세스 크기에 맞게 메모리를 1/2로 자르고 프로세스를 메모리에 배치한다

나뉜 메모리의 각 구격에는 프로세스가 1개만 들어간다

프로세스가 종료되면 주변의 빈 조각과 합쳐서 하나의 큰 덩어리를 만든다

Last updated