본문 바로가기
임베디드 개발/리눅스 디바이스 드라이버

LDD ] 커널 메모리 할당 함수 (kmalloc, kzalloc 등)

by eteo 2025. 3. 12.

 

 

 

kmalloc / kzalloc

kmalloc과 kzalloc은 커널 공간에서 연속된 메모리를 동적으로 할당하는 함수로, 사용자 공간의 malloc, calloc과 유사하지만 커널 내부에서만 사용된다.

 

참고로 이 두 함수로 할당 가능한 최대 메모리 크기는 시스템의 page size에 의존하며, 일반적인 page size인 4KB보다 작은 크기의 객체를 할당할 때만 사용하는 것이 권장된다. 만약 4KB 이상의 메모리를 할당하려면 vmalloc 등 다른 메모리 할당 함수를 사용해야 한다.

 

한편 이 두 함수를 사용에 할당된 메모리는 사용이 끝나면 반드시 kfree를 통해 해제하여 메모리 누수를 방지해야 한다.

 

kmalloc과 kzalloc의 차이는 다음과 같다.

  • kmalloc : 할당된 메모리는 초기화되지 않는다.
  • kzalloc : kmalloc과 동일하지만 할당된 메모리를 0으로 초기화한다. 초기화되지 않은 메모리를 사용하는 오류를 방지하는 데 유용하다.

 

void *kmalloc(size_t size, gfp_t flags);
void *kzalloc(size_t size, gfp_t flags);

 

  • size : 할당할 메모리 크기(바이트 단위)
  • flags : 메모리 할당 동작을 지정하는 플래그
  • 반환 값 : 성공 시 할당된 메모리 주소(void *), 실패 시 NULL 반환

 

 

 

 

 

GFP 플래그

gfp_t 타입의 flags 인자는 메모리 할당 시 커널의 동작을 제어한다.

 

  • GFP_KERNEL : 일반적인 커널 모드 메모리 할당에 사용되며, 가장 흔하게 사용되는 플래그이다. 메모리 부족 시 커널이 메모리를 확보할 때까지 프로세스를 블로킹 상태에 둘 수 있다.
  • GFP_ATOMIC : 인터럽트 컨텍스트나 슬립이 허용되지 않는 상황에서 사용되며, 할당 실패 시 즉시 NULL을 반환한다.
  • GFP_DMA : DMA에서 사용 가능한 메모리 영역을 할당할 때 사용한다.
  • GFP_NOWAIT : 메모리 부족 시 즉시 NULL 반환을 원할 때 사용한다.
  • GFP_HIGHUSER : 사용자 공간 메모리 할당에 사용한다.

 

 

 

 

kfree

void kfree(const void *ptr);
  • ptr : kmalloc 또는 kzalloc으로 할당된 메모리의 포인터. NULL을 전달하면 아무 작업도 수행하지 않는다.

 

 

 

 

 

devm_* (devm_kmalloc, devm_kzalloc)

devm_* 계열 함수는 드라이버가 언로드될 때와 로드 중 실패가 발생한 경우 자동으로 메모리를 해제하기 때문에 실수로 인한 메모리 누수를 방지한다. 명시적인 kfree 호출이 필요하지 않고 디바이스 드라이버 코드를 간결하게 만들 수 있다.

 

초기화가 필요한 경우 devm_kzalloc을 사용하고, 초기화가 필요하지 않으면 devm_kmalloc을 사용하면 된다.

 

void *devm_kmalloc(struct device *dev, size_t size, gfp_t flags);
void *devm_kzalloc(struct device *dev, size_t size, gfp_t flags);

 

  • dev : 할당된 메모리를 관리할 디바이스 구조체 포인터
  • 그 외 인자와 반환 값은 kmalloc / kzalloc과 동일하다.

 

 

 

 

 

사용 예시

 

- kmalloc() 및 kfree() 사용 예시.

void *buf = kmalloc(256, GFP_KERNEL);
if (!buf) {
    printk("Memory allocation failed\n");
    return -ENOMEM;
}
// ...
kfree(buf);

 

 

- devm_kzalloc() 사용 예시.

void *buf = devm_kzalloc(pdev, 256, GFP_KERNEL);
if (!buf) {
    dev_err(dev, "Memory allocation failed\n");
    return -ENOMEM;
}

 

 

 

 

 

 

 

 

관련 유사 함수들

void *kmalloc_array(size_t n, size_t size, gfp_t flags);
void *kcalloc(size_t n, size_t size, gfp_t flags);
void *krealloc(const void *ptr, size_t new_size, gfp_t flags);
void kzfree(const void *ptr);
  • kmalloc_array : 요소 개수 n과 각 요소 크기 size로 여러 요소를 할당한다. 메모리 할당 전 내부적으로 n * size가 정수 오버플로우를 일으키는지 확인하는 절차가 있다.
  • kcalloc : kmalloc_array와 비슷하게 동작하나 할당된 메모리를 0으로 초기화한다.
  • krealloc : 기존에 할당된 메모리를 새로운 크기로 재할당한다. 기존 데이터는 유지된다.
  • kzfree : 메모리를 해제하기 전에 내용을 0으로 초기화한 뒤 메모리를 해제한다.