>  기사  >  백엔드 개발  >  C로 자신만의 메모리 풀 할당자 작성하기

C로 자신만의 메모리 풀 할당자 작성하기

Linda Hamilton
Linda Hamilton원래의
2024-11-20 03:33:02805검색

Writing Your Own Memory Pool Allocator in C

C에서 자신만의 메모리 풀 할당자 작성: 단계별 가이드

C에서 동적 메모리 관리는 특히 성능이 중요한 애플리케이션에서 효율적인 소프트웨어를 개발하는 데 중요한 측면입니다. 표준 라이브러리의 malloc() 및 free()와 같은 함수가 일반적으로 사용되지만 자주 호출하면 조각화 및 할당 시간이 느려지는 등의 오버헤드와 제한이 따릅니다. 이러한 문제에 대한 한 가지 해결책은 메모리 풀 할당자를 만드는 것입니다.

이 블로그에서는 C에서 처음부터 간단한 메모리 풀 할당자를 작성하는 방법을 살펴보겠습니다. 메모리 풀을 사용하면 큰 메모리 블록을 사전 할당하고 수동으로 관리하여 조각화를 줄이고 메모리를 향상시킬 수 있습니다. 할당실적.

? Twitter(X)에서 계속 대화를 이어가세요: @trish_07

메모리 풀 할당자란 무엇입니까?

메모리 풀 할당자는 큰 메모리 블록이 사전 할당되고, 필요에 따라 더 작은 덩어리가 프로그램에 전달되는 사용자 정의 메모리 관리 전략입니다. 메모리가 더 이상 필요하지 않으면 재사용을 위해 풀로 반환됩니다. 이 접근 방식을 사용하면 malloc() 및 free()를 직접 사용하는 것보다 더 빠른 할당 및 할당 해제가 가능하고 메모리 활용도도 향상됩니다.

기본 메모리 풀의 작동 방식은 다음과 같습니다.

  • 큰 메모리 블록을 미리 할당합니다.
  • 이 블록을 더 작은 덩어리(블록)로 나눕니다.
  • 무료 목록에서 사용하지 않은 블록을 추적하세요.
  • 블록이 요청되면 풀에서 할당하고 호출자에게 반환합니다.
  • 블록이 해제되면 풀로 반환합니다.

1단계: 메모리 풀 구조 정의

메모리 풀과 그 안에 있는 블록에 대한 간단한 구조를 정의하는 것부터 시작하겠습니다. 각 블록에는 사용 가능 목록의 다음 블록에 대한 포인터가 있으므로 메모리를 빠르게 할당하고 해제할 수 있습니다.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

#define POOL_SIZE 1024  // Total memory pool size

// Define a block structure with a pointer to the next free block
typedef struct Block {
    struct Block *next;
} Block;

// Define the MemoryPool structure
typedef struct {
    Block *freeList;
    unsigned char pool[POOL_SIZE]; // Pre-allocated pool
} MemoryPool;

이 코드에서는:

  • POOL_SIZE는 메모리 풀의 전체 크기입니다. 풀을 시뮬레이션하기 위해 정적 배열을 할당하겠습니다.
  • 블록 구조는 단일 메모리 덩어리를 나타내며 이를 사용 가능한 목록의 다음 블록에 연결하는 포인터(다음)를 포함합니다.
  • MemoryPool 구조에는 freeList 포인터(사용 가능한 블록을 추적함)와 실제 사전 할당된 메모리를 보유하는 풀 배열이 포함되어 있습니다.

2단계: 메모리 풀 초기화

메모리 풀을 초기화하려면 풀을 블록으로 나누고 사용 가능한 목록을 설정해야 합니다. 각 블록은 다음 사용 가능한 블록을 가리켜야 합니다.

void initMemoryPool(MemoryPool *pool) {
    pool->freeList = (Block *)pool->pool;
    Block *current = pool->freeList;

    // Create a free list of blocks
    for (int i = 0; i < (POOL_SIZE / sizeof(Block)) - 1; i++) {
        current->next = (Block *)((unsigned char *)current + sizeof(Block));
        current = current->next;
    }

    current->next = NULL; // Last block points to NULL
}

이 기능의 내용:

  • 풀의 시작 부분을 가리키도록 freeList를 초기화합니다.
  • 그런 다음 풀을 반복하면서 각 블록의 다음 포인터를 메모리의 다음 포인터로 설정합니다.
  • 마지막으로 마지막 블록은 사용 가능 목록의 끝을 나타내기 위해 NULL을 가리킵니다.

3단계: 풀에서 메모리 할당

메모리를 할당하려면 사용 가능 목록에서 사용 가능한 첫 번째 블록을 가져와야 합니다. 블록을 할당하고 나면 사용 가능 목록에서 해당 블록을 제거합니다.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

#define POOL_SIZE 1024  // Total memory pool size

// Define a block structure with a pointer to the next free block
typedef struct Block {
    struct Block *next;
} Block;

// Define the MemoryPool structure
typedef struct {
    Block *freeList;
    unsigned char pool[POOL_SIZE]; // Pre-allocated pool
} MemoryPool;

이 함수는 사용 가능한 목록이 비어 있는지 확인합니다. 그렇지 않은 경우 첫 번째 사용 가능한 블록을 가져와 사용 가능한 목록에서 제거한 후 호출자에게 반환합니다.

4단계: 메모리를 확보하고 풀에 다시 추가

메모리가 해제되면 블록을 사용 가능 목록으로 되돌립니다. 이를 통해 향후 할당에 재사용할 수 있습니다.

void initMemoryPool(MemoryPool *pool) {
    pool->freeList = (Block *)pool->pool;
    Block *current = pool->freeList;

    // Create a free list of blocks
    for (int i = 0; i < (POOL_SIZE / sizeof(Block)) - 1; i++) {
        current->next = (Block *)((unsigned char *)current + sizeof(Block));
        current = current->next;
    }

    current->next = NULL; // Last block points to NULL
}

여기서 다음 포인터를 사용 가능 목록의 현재 첫 번째 블록으로 설정하여 사용 가능한 블록을 사용 가능 목록 앞에 추가합니다. 이를 통해 향후 블록을 재사용할 수 있습니다.

5단계: 사용 예

이제 필요한 모든 기능이 준비되었으므로 모든 것을 하나로 모아 메모리 풀 할당자를 테스트해 보겠습니다.

void *allocateMemory(MemoryPool *pool) {
    if (pool->freeList == NULL) {
        printf("Memory pool exhausted!\n");
        return NULL;
    }

    // Get the first free block
    Block *block = pool->freeList;
    pool->freeList = block->next; // Move the free list pointer

    return (void *)block;
}

이 예에서는:

  • initMemoryPool()을 사용하여 메모리 풀을 초기화합니다.
  • 그런 다음 할당메모리()를 사용하여 두 개의 블록을 할당합니다.
  • 마지막으로 freeMemory()를 사용하여 블록을 해제합니다.

이 프로그램을 실행하면 다음과 유사한 출력이 표시됩니다.

void freeMemory(MemoryPool *pool, void *ptr) {
    Block *block = (Block *)ptr;
    block->next = pool->freeList; // Add the block to the free list
    pool->freeList = block;
}

메모리 풀을 사용하는 이유는 무엇입니까?

  1. 성능: 시스템 수준 메모리 관리 오버헤드가 최소화되므로 메모리 풀은 일반적으로 malloc() 및 free()를 반복적으로 호출하는 것보다 빠릅니다.
  2. 조각화 방지: 메모리 풀은 고정 크기의 메모리 블록을 할당하여 조각화를 방지하는 데 도움이 됩니다.
  3. 예측성: 프로그램이 할당과 할당 취소를 제어하므로 메모리 할당을 예측할 수 있습니다.

메모리 풀은 짧은 지연 시간과 메모리 효율성이 중요한 실시간 시스템, 임베디드 시스템게임에 특히 유용합니다.

결론

자신만의 메모리 풀 할당자를 작성하면 성능이 중요한 애플리케이션의 메모리 관리를 크게 최적화할 수 있습니다. 메모리를 직접 관리하면 할당 속도를 향상시키고 조각화를 줄이며 프로그램에서 메모리가 사용되는 방식을 더 효과적으로 제어할 수 있습니다. 이 예제는 기본이지만 다양한 블록 크기 또는 스레드로부터 안전한 메모리 할당과 같은 추가 기능을 사용하여 확장할 수 있습니다.

효율적인 메모리 관리가 필요한 프로젝트를 진행하고 있다면 자체 메모리 풀 구현을 고려해 보세요. 메모리 관리에 대해 더 자세히 알아보고 애플리케이션 성능을 향상시킬 수 있는 좋은 방법입니다.


질문이 있거나 추가 설명이 필요한 경우 언제든지 문의해 주세요. 즐거운 코딩하세요! ?

위 내용은 C로 자신만의 메모리 풀 할당자 작성하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.