[운영체제] 동적 메모리 할당

유선·2024년 4월 12일
0

CS

목록 보기
9/25
post-thumbnail

동적 메모리 할당?

  • 동적 메모리 할당기는 힙(heap)이라고 하는 프로세스의 가상메모리 영역을 관리한다.
    • 힙(heap)은 프로그램 실행 중 동적으로 할당되는 메모리 공간을 관리하는 메모리 영역이다.
  • 동적 메모리 할당을 사용하는 가장 중요한 이유는 프로그램을 실행시키기 전에는 자료 구조의 크기를 알 수 없는 경우들이 있기 때문이다.

  • 커널은 힙 영역의 꼭대기를 가리키는 포인터(brk ptr)를 사용한다.(변수 brk "break"라고 발음)
  • 메모리 할당기는 힙을 다양한 크기의 블록 단위로 관리한다.

💡 동적 메모리 할당을 하는 주요 두 가지 방법!

  • 1️⃣ 명시적 할당(Explicit Allocation)
    • 프로그래머가 직접 메모리를 할당하고 해제한다.
    • 대표적으로 C나 C++에서 malloc(), calloc(), realloc() 함수를 사용하여 메모리를 할당하고 free() 함수를 사용하여 메모리를 해제
    • 장점: 메모리 관리를 직접적으로 제어할 수 있다
    • 단점: 잘못된 사용으로 메모리 누수(memory leaks)해제된 메모리를 참조하는 경우에 발생하는 오류 등을 유발할 수 있다.
  • 2️⃣ 묵시적 할당(Implicit Allocation)
    • 자동으로 메모리가 할당되고 해제된다.
    • 대표적으로 Java, Python과 같은 고수준 프로그래밍 언어에서는 개발자가 명시적으로 메모리를 할당하거나 해제할 필요가 없다.
      • 대신, 가비지 컬렉션(Garbage Collection)과 같은 메커니즘이 사용되어 더 이상 필요하지 않은 객체들의 메모리를 자동으로 회수한다.
    • 장점: 개발자가 메모리 관리에 대한 부담을 덜어준다.
    • 단점: 가비지 컬렉션의 동작에 따른 성능 저하가 발생할 수 있다.

malloc

  • C 표준 라이브러리는 malloc 패키지로 알려진 명시적인 할당기를 제공
#include <stdlib.h>

void * malloc(size_t size);
  • 프로그램은 malloc 함수를 호출해서 으로부터 블록들을 할당받는다.
  • 블록 내에 포함될 수 있는 어떤 종류의 데이터 객체에 대해서 적절히 정렬된 최소 size 바이트를 갖는 메모리 블록의 포인터를 반환한다.
  • 32비트 모드인 경우 주소는 8의 배수, 64비트 모드인 경우 16의 배수를 리턴한다.
  • 만일 프로그램이 가용한 가상메모리보다 더 큰 크기의 메모리 블록을 요청한 경우 NULL을 반환하며 errno를 설정한다.
  • malloc은 리턴하는 메모리를 초기화하지 않는다. 만약, 초기화 원한다면 calloc을 사용할 수 있다.
  • 할당된 블록의 크기를 변경하고 싶은 경우 realloc 함수를 사용할 수 있다.
#include <stdlib.h>

void * realloc(void * p, size_t size);
  • realloc은 블록 p의 크기를 변경하고, 새 블록의 포인터를 리턴한다.

sbrk

  • malloc같은 동적 메모리 할당기는 mmap과 munmap 함수를 사용하여 명시적으로 힙 메모리를 할당하거나, 혹은 sbrk 함수를 사용할 수 있다.
#include <unistd.h>

void * sbrk(intptr_t incr);
  • sbrk 함수는 커널의 brk 포인터에 incr을 더해서 힙을 늘리거나 줄인다.
  • 성공한다면 이전의 brk 값을 리턴하고, 실패한다면 -1을 리턴하고 errno를 ENOMEM으로 설정

free

  • 프로그램들은 할당된 힙 블록을 free 함수를 호출해서 반환한다.
#include <stdlib.h>

void free(void * ptr);
  • ptr 인자는 malloc, calloc, realloc에서 획득한 할당된 블록의 시작을 가리켜야한다.
  • 그렇지 않다면, free의 동작은 정의되지 않는다.

💡 힙 영역 예시

  • 각 블록은 워드 단위이다.

💡 malloc과 free사용해서 블록을 할당하고 반환시키기

  • 위 그림은 C 프로그램에 대하여 16 워드의 작은 힙을 malloc과 free가 어떻게 관리하는지를 보여준다.
  • 동일한 색의 워드들은 하나의 블록을 이룬다.

💡 할당기 요구사항

  • 🌟 임의의 요청 순서 처리
    • 응용 프로그램은 각각의 가용 블록이 이전의 할당 요청에 의해 현재 할당된 블록에 대응되어야 한다는 제한사항을 만족하면서 임의의 순서로 할당과 반환요청을 할 수 있다.
    • 할당기는 할당과 반환 요청의 순서에 대해 아무런 가정을 할 수 없다.
  • 🌟 요청에 즉시 응답하기
    • 할당기는 블록들을 이들이 어떤 종류의 데이터 객체라도 저장할 수 있도록 하는 방식으로 정렬해야한다.
  • 🌟 힙만 사용하기
    • 할당기가 사용하는 비확장성 자료 구조들은 힙자체에 저장되어야 한다.
  • 🌟 블록 정렬하기
    • 어떤 종류의 데이터 객체라고 저장할 수 있도록 하는 방식으로 정렬해야한다.
  • 🌟 할당된 블록을 수정하지 않기
    • 할당기는 가용블록을 조작하거나 변경할 수 만 있다.
  • 개발자는 성능을 내기 위해 처리량메모리 이용도최대화하기 위하여 노력한다.

※ 🤔 목표1: 처리량 극대화 하기

  • 단위 시간(1 초)동안에 완료한 요청의 수
  • 할당기가 500개의 할당 요청500개의 반환 요청을 1초 동안에 완료한다면, 이 경우 처리량은 초당 1,000 연산이다.

※ 🤔 목표2: 메모리 이용도를 최대화 하기

  • 가상메모리의 양은 디스크 내의 스왑 공간의 양에 의해 제한되기 때문에 유한함
  • 최고 이용도(peak utilization) :
    • n개의 할당, 반환 요청의 배열의 주어지고 어떤 application이 p 바이트 블록을 요청하면, 할당된 블록은 데이터 p 바이트를 가짐
    • 요청 R_k가 완료된 후 종합 데이터 P_k는 현재 할당된 블록들의 데이터들의 합, H_k는 현재 힙의 크기
    • 첫 번째 k 요청에 대한 최고 이용도 Uk=maxikPi/HkU_k = max_{i≤k}P_i/H_k

처리량, 이용도를 최대화 하는 데 긴장이 존재하므로 이 둘 사이에서 적절한 균형을 찾는 것이 중요하다.

malloc과 free 구현 이슈

  • 처리량과 이용도 사이에 좋은 균형을 갖는 실용적인 할당기는 다음 이슈들을 고려해야한다.
  1. 가용 블록 구성: 어떻게 가용 블록을 지속적으로 추적하는가?
  2. 배치 : 새롭게 할당된 블록을 배치하기 위한 가용 블록을 어떻게 선택하는가?
  3. 분할 : 새롭게 할당한 블록을 가용 블록에 배치한 후 가용 블록의 나머지 부분들로 무엇을 할 것인가?
  4. 연결 : 방금 반환된 블록으로 무엇을 할 것인가?
사진 참고자료
profile
Sunny Day!

0개의 댓글