포스트

임베디드 스터디 - 버퍼 관리와 메모리 할당

임베디드 스터디 - 버퍼 관리와 메모리 할당

copy_to_user() / copy_from_user()

  • 드라이버가 커널 버퍼 데이터를 사용자 공간으로 전달할 때 memcpy() 대신 반드시 사용해야 함
  • 사용자 공간 포인터는 신뢰할 수 없는 값 — 잘못된 주소, 커널 영역 주소, 널 포인터일 수 있음
1
2
3
4
// 사용자가 넘긴 포인터가 이런 값이라면?
void *user_ptr = (void *)0xFFFF0000;  // 커널 영역 주소
void *user_ptr = NULL;                // 널 포인터
void *user_ptr = (void *)0xDEADBEEF; // 완전히 잘못된 주소
  • copy_to_user() 내부 동작
1
2
3
4
5
6
copy_to_user(user_ptr, kernel_buf, size)
        
1. user_ptr 실제 사용자 공간 주소인지 검증
2. user_ptr + size 범위가 유효한지 검증
3. 검증 통과   데이터 복사
4. 검증 실패   EFAULT 반환 (복사  )
함수방향사용 시점
copy_to_user()커널 → 사용자read() 구현 시
copy_from_user()사용자 → 커널write() 구현 시

kmalloc() / kfree()

  • 커널 공간에서 동적 메모리를 할당/해제하는 함수
  • 사용자 공간의 malloc()/free()에 대응
1
2
void *buf = kmalloc(size, flags);  // 할당
kfree(buf);                         // 해제
  • 물리적으로 연속된 메모리를 할당 → 일반적으로 수십 KB 이하 권장

GFP_KERNEL vs GFP_ATOMIC

  • 메모리 부족 시 SLEEP 가능 여부가 핵심 차이
플래그메모리 부족 시 동작사용 컨텍스트
GFP_KERNELSLEEP 하며 대기일반 커널 코드, work_queue
GFP_ATOMIC즉시 실패 반환인터럽트 핸들러, tasklet
1
2
3
어디서 할당하는가?
├── 일반 커널 코드, work_queue → GFP_KERNEL (sleep 가능)
└── 인터럽트 핸들러, tasklet  → GFP_ATOMIC (sleep 불가)

vmalloc()

  • kmalloc()은 물리적으로 연속된 메모리를 할당 → 크기가 클수록 메모리 파편화 문제로 연속 공간 찾기 어려움
  • vmalloc()은 가상 주소 공간에서 연속, 물리는 불연속 허용 → 대용량 메모리 할당 가능
1
2
3
kmalloc()  물리 메모리: [████████] 연속 필요
vmalloc()  물리 메모리: [████][  ][██] 불연속 허용
           가상 메모리: [██████████] 연속으로 보임
 kmalloc()vmalloc()
물리 메모리물리적 연속불연속 허용
적합한 크기수십 KB 이하수 MB 이상
DMA 사용✅ 가능❌ 불가
오버헤드낮음가상-물리 매핑 오버헤드 있음
주요 용도드라이버 내부 버퍼, DMA대용량 버퍼
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.