kimyu0218
  • [OS] 메모리 관리 1편 (주소 바인딩/메모리 로드)
    2024년 02월 07일 23시 35분 36초에 업로드 된 글입니다.
    작성자: @kimyu0218

    메모리는 프로그램이 실행될 때 필요한 데이터를 일시적으로 저장하는 공간이다. 운영체제는 이러한 메모리를 효율적으로 활용하여 다음과 같은 작업을 수행한다.

    • 프로세스를 실행하기 위해 필요한 메모리를 할당하고 해제한다. 여러 프로세스가 동시에 실행될 때 메모리를 적절히 분배하여 각 프로세스가 충돌 없이 실행될 수 있도록 한다.
    • 가상 메모리를 활용하여 물리적 메모리의 한계를 극복한다. 이를 통해 더 많은 프로세스를 동시에 실행할 수 있다.

     

    메모리 관리

    It determines how memory is allocated among competing processes, deciding which gets memory, when they receive it, and how much they are allowed.

    메모리 관리는 프로세스가 실행될 때 메모리를 할당하고, 프로세스가 종료될 때 이를 회수하여 시스템의 자원을 효율적으로 활용하는 것을 목표로 한다.
     

    주소 바인딩

    메모리는 주소를 사용하여 데이터를 저장하고 참조한다. 이 주소는 크게 논리적 주소와 물리적 주소로 나뉜다.
     

    논리적 주소와 물리적 주소

    논리적 주소프로세스가 메모리에 접근할 때 사용하는 주소다. 프로그램이 실행되면 운영체제는 프로세스에게 독자적인 논리적 주소 공간을 할당한다. 이 주소는 CPU가 참조하는 주소로, 프로세스가 메모리에 접근할 때 CPU는 해당 주소를 사용하여 데이터를 읽고 쓴다. 반면, 물리적 주소실제 메모리의 위치를 나타낸다.
     

    주소 바인딩

    프로세스가 논리적 주소를 참조하기 때문에 실제 메모리에 데이터를 읽고 쓰기 위해서는 해당 논리적 주소를 물리적 주소로 매핑하는 과정이 필요하다. 이를 주소 바인딩이라고 부른다. 주소 바인딩은 프로세스가 메모리에 접근할 수 있도록 하는 중요한 단계로, 주로 세 가지 시점에서 이루어진다.
     

    컴파일 타임 바인딩 로드 타임 바인딩 런타임 바인딩
    프로그램이 컴파일되는 시점 프로그램이 메모리에 로드되는 시점 프로그램이 실행되는 동안
    프로그램 실행 전에 주소가 고정되므로 실행 시에 주소 변환이 필요하지 않아 런타임 오버헤드가 감소한다. 프로그램을 실행하는 동안 주소를 변경할 수 있어 메모리 관리의 유연성이 높다.
    프로그램 실행 전에 주소가 이미 결정되어 있기 때문에 메모리의 유연성이 제한된다. 주소 변환에 따른 오버헤드가 발생하고, 실행 속도가 감소한다.

     

    MMU

    MMU : memory management unit (= PMMU : paged memory management unit)

    MMU는 논리적 주소를 물리적 주소로 매핑하는 장치다. 지금부터 MMU의 동작 과정을 살펴보자.

    1. 프로세스가 논리적 주소를 사용하여 메모리에 접근하면 (by CPU) MMU가 동작한다.
    2. MMU는 주소 변환 테이블을 통해 논리적 주소를 물리적 주소로 변환한다.
    3. 변환된 물리적 주소를 사용하여 메모리에 접근하고 데이터를 읽거나 쓴다.

    MMU는 주소를 변환하는 과정에서 두 개의 레지스터를 사용한다.

    1. base 레지스터 - 논리적 주소 공간이 실제 메모리에서 시작되는 위치 (= relocation 레지스터)
    2. limit 레지스터 - 프로세스가 할당된 메모리 공간의 크기 (프로그램의 크기!)

    프로세스가 논리적 주소를 참조하면, MMU는 해당 주소를 base 레지스터 값에 더하고, 그 결과를 limit 레지스터 값과 비교하여 유효성을 검사한다. (limit 레지스터는 base 레지스터가 지정한 시작 위치로부터 얼마나 큰 주소 공간을 사용할 수 있는지 제한하는 역할을 수행한다!)

    💡 limit 레지스터는 프로세스가 범위를 벗어나는 주소에 접근하는 것을 제한하여 메모리를 보호한다.

     

    메모리 로드

    메모리 로드는 프로그램이 메모리에 어떻게 배치되고, 어떻게 관리되는지를 결정한다. 이는 시스템의 성능에 상당한 영향을 미친다.
     

    dynamic loading

    동적 로딩은 프로그램 실행 시에 필요한 라이브러리나 모듈을 필요한 시점에 메모리에 동적으로 로드하는 것을 의미한다. 즉, 프로세스 전체를 한 번에 메모리에 로드하는 것이 아니라, 필요한 함수나 모듈이 실제로 호출될 때만 로드하여 사용한다. 이는 프로그램 실행 속도를 향상시키고 메모리 사용량을 줄인다.
     

    dynamic linking

    동적 링킹은 linking*을 런타임까지 미루는 기법으로, 필요한 외부 라이브러리나 모듈의 코드를 실행 파일과 분리된 공유 라이브러리 파일에 유지한다.  즉, 프로그램이 실행될 때 외부 라이브러리나 모듈의 코드를 실행 파일에 포함시키지 않고 필요할 때 라이브러리를 동적으로 연결한다. 이는 프로그램의 크기를 줄여 메모리가 낭비되는 것을 방지한다.

    *linking : 여러 소스 파일에 나누어 작성된 코드를 하나의 프로그램으로 결합하는 과정
    🚨 정적 링킹은 컴파일 시에 필요한 외부 라이브러리와 모듈의 코드를 실행 파일에 포함시킨다. 동적 로딩에 비해 실행 파일의 크기가 상대적으로 크기 때문에 메모리가 낭비될 수 있지만, 실행 속도는 더 빠르다.

     

    overlays

    오버레이는 프로세스의 크기가 메모리보다 클 때, 프로그램을 여러 부분으로 나누어 로드하는 방식이다.
     

    swapping

    스와핑은 메모리에 로드된 프로세스를 메모리에서 디스크 (스왑 영역) 로 옮기는 기법이다. 메모리가 부족한 경우, 가장 오랫동안 사용되지 않은 프로세스를 스왑 아웃*하여 메모리를 확보한다.

    *swap out : 메모리에서 쫓아내기 (↔ swap in : 메모리에 다시 올리기)
    🚨 스와핑은 프로세스의 전체 컨텍스트를 저장하고 복원해야 하므로 오버헤드가 발생한다. 따라서 스와핑이 과도하게 발생할 경우, 시스템의 성능에 부정적인 영향을 미칠 수 있다.

    참고자료

    댓글