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으로 초기화한 뒤 메모리를 해제한다.
'임베디드 개발 > 리눅스 디바이스 드라이버' 카테고리의 다른 글
LDD ] Device Tree (DT) (0) | 2025.03.27 |
---|---|
LDD ] PCIe 디바이스 드라이버 작성하기 - (4) with sysfs (0) | 2025.03.18 |
LDD ] PCIe 디바이스 드라이버 작성하기 - (3) with Interrupt (0) | 2025.03.03 |
LDD ] 커널 시간 관련 함수 사용법 (0) | 2025.02.27 |
Linux Kernel ] Container_of (0) | 2025.02.06 |