Skip to content

Latest commit

 

History

History
120 lines (93 loc) · 4.74 KB

File metadata and controls

120 lines (93 loc) · 4.74 KB

메모리 할당과 해제 (5장)

1. 변수 선언

지역 변수 vs 전역 변수

  • 지역/전역 모두 커널 메모리 공간에 배치됨.
  • 다중 프로세스 환경이므로 경쟁 조건(Race Condition) 방지를 위해 가급적 지역 변수 사용 권장.
  • 모듈 적재~해제 시점까지 유지해야 하는 정보는 전역 변수로 지정.

이식성을 위한 데이터형 (#include <asm/types.h>)

부호 있는 정수 부호 없는 정수 크기
__s8, s8 __u8, u8 8비트 (1 Byte)
__s16, s16 __u16, u16 16비트 (Word)
__s32, s32 __u32, u32 32비트
__s64, s64 __u64, u64 64비트
  • int 형 주의: 16비트 프로세서 → 2Byte, 32비트 → 4Byte, 64비트 → 8Byte로 플랫폼 의존적. 이식성 필요 시 커널 제공 타입 사용.

구조체 패킹 (__attribute__((packed)))

컴파일러 정렬 패딩 없이 실제 변수 크기로 선언. 레지스터 표현이나 정확한 데이터 교환 시 필요.

typedef struct {
    u16 index;
    u16 data;
    u8  data2;
} __attribute__((packed)) testctl_t;

바이트 순서 (Endianness)

  • #include <asm/byteorder.h> 포함 시 __LITTLE_ENDIAN 또는 __BIG_ENDIAN이 정의됨.

I/O 메모리 접근 변수: volatile

컴파일러 최적화로 레지스터 접근이 생략되는 것을 방지.

volatile u32 *ptr = (volatile u32 *)0xE0000300;
*ptr = 0x1234;  // 반드시 메모리에 접근하여 처리

2. 동적 메모리

커널 메모리의 특수성 (일반 malloc()을 사용할 수 없는 이유)

  • 커널/프로세스 메모리 공간 분리: 커널은 물리 메모리에 직접 접근하고 MMU를 고려한 처리 필요.
  • PAGE_SIZE 단위 할당: 보통 4KB(PAGE_SIZE = 4096). 메모리 단편화 방지.
  • 가용 메모리 부족 상황 처리 필요: 커널 메모리는 가상 메모리 페이징을 사용하지 않으므로 할당 실패 가능.
  • 연속된 물리 메모리 필요: DMA 컨트롤러는 물리적으로 연속된 메모리 주소 요구.
  • 인터럽트 컨텍스트: 인터럽트 상태에서 메모리 잠금(Sleep) 불가. 즉각 할당 필요.

kmalloc() / kfree() - 가장 많이 사용

#include <linux/slab.h>

char *buff;
buff = kmalloc(1024, GFP_KERNEL);
if (buff != NULL) {
    kfree(buff);
} else {
    printk("kmalloc error\n");
}
  • 할당 속도 빠름, 사용법 간단. malloc()과 유사.
  • 할당 가능 크기 제한: 32 × PAGE_SIZE = 약 131,072 Byte 이하.
플래그 동작
GFP_KERNEL 메모리 부족 시 프로세스가 잠들어 대기. 인터럽트 서비스 루틴 사용 불가
GFP_ATOMIC 메모리 없으면 즉시 NULL 반환. 잠들지 않음. 인터럽트 컨텍스트에서 사용
GFP_DMA 물리적으로 연속된 메모리 할당. DMA 컨트롤러 사용 시 필요

vmalloc() / vfree() - 대용량 할당

#include <linux/vmalloc.h>

char *buff;
buff = vmalloc(1024);
if (buff != NULL) {
    vfree(buff);
} else {
    printk("vmalloc error\n");
}
  • 가상 공간이 허용하는 한 크기 제한 없이 할당 (크기 제한 없음).
  • 가상 메모리 관리 루틴이 수행되어 kmalloc()보다 할당 속도 느림.
  • 할당 주소의 물리 주소 획득 실패 가능 (스왑된 경우).
  • 인터럽트 서비스 함수 내 사용 불가 (잠드는 인자가 없음).

__get_free_pages() / free_pages() - 페이지 단위 할당

// 커널 2.4: #include <linux/mm.h>
// 커널 2.6: #include <linux/gfp.h>
#include <asm/page.h>   // get_order() 사용 시

char *buff;
int order;

order = get_order(8192);                       // 8192 Byte에 필요한 차수 계산
buff = __get_free_pages(GFP_KERNEL, order);    // PAGE_SIZE * 2^order 크기 할당
if (buff != NULL)
    free_pages(buff, order);
  • order: PAGE_SIZE의 2승수. 최대값은 MAX_ORDER(보통 11). 실용적으로 5 이하(32 × PAGE_SIZE) 사용.
  • kmalloc()의 최대 할당량과 동일한 수준.

3. 메모리 할당 함수 비교

함수 최대 크기 속도 물리 연속성 인터럽트 내 사용 특징
kmalloc(GFP_KERNEL) 32 × PAGE_SIZE 빠름 보장 불가 가장 일반적 사용
kmalloc(GFP_ATOMIC) 32 × PAGE_SIZE 빠름 보장 가능 실패 가능성 있음
vmalloc() 가상 메모리 한도 느림 보장 안 됨 불가 대용량 할당 시 사용
__get_free_pages() MAX_ORDER 제한 중간 보장 GFP 플래그 따름 페이지 단위 관리 필요

[새로운내용]