Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

꾸준히

디바이스 드라이버에서 변수와 메모리 할당 본문

Device Driver

디바이스 드라이버에서 변수와 메모리 할당

S210530 2023. 7. 9. 16:54

디바이스 드라이버에서 변수와 메모리 할당에 관한 내용을 정리하는 글입니다.
디바이스 드라이버에서 변수의 사용, 이식성과 데이터 형, 커널에서의 동적 메모리에 대해 설명합니다.

 

디바이스 드라이버에서 변수와 메모리 할당

 

목차

 

1. 변수의 사용

2. 이식성과 데이터 형

3. 커널에서의 동적 메모리 관리

 

 

변수의 사용

디바이스 드라이버는 다중 프로세스 환경에서 동작하기 때문에 프로세스간 변수 사용에 따른 경쟁 문제를 해결하기 위해 가급적 지역 변수를 사용하는 편이 좋다. 하지만 해제되는 시점까지 유지해야 하는 정보라면 전역 변수로 지정해야 한다.

변수 명 사용 시 static을 주로 사용한다. 커널 소스는 방대한 함수와 전역 변수가 있으므로, 이것이 서로 중복되지 않도록 하기 위해 static으로 선언하는 습관을 들이는 것이 좋다. static을 사용하면 소스에서만 참조하고 심볼 테이블에는 유지하지 않는다.

static int count = 0;           // 변수 선언의 예
static int dev_app_check(void); // 함수 선언의 예

static void dd_sample(void)
{
    // 지역 변수 안에 static을 쓰지 않는다
    // (전역 변수처럼 되기 때문에)
}

 

이식성과 데이터 형

변수의 데이터 형에 대한 이식성 문제

다른 플랫폼에서 문제없이 수행되려면 변수의 데이터 형을 명확히 해야 한다.
가장 문제가 되는 int형 → 커널에서 제공하는 데이터 형을 사용한다.

#include <asm/types.h>에 선언되어 있으며, 밑줄 두 개가 붙은 타입은 응용 프로그램에서 사용할 수 있는 변수형이다.

구조체의 이식성

구조체는 대부분 int형의 배수로 선언된다. 디바이스 컨트롤러의 레지스터를 표현할 경우 응용 프로그램과 정확한 데이터 교환을 위해 int의 배수로 정렬되면 곤란한 경우가 있다. packed 라는 키워드를 사용해 실제 변수 크기로 선언되도록 한다.

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

 

I/O 메모리 접근 변수 처리

메모리 번지를 이용하는 I/O 처리는 최적화 등에 의해 의도 되지 않은 형태로 변할 수 있으므로 주의를 기울인다.

ex) 0xE0000300 번지에서 데이터를 읽고 쓰기 예제

<코드 원본>

u32 *ptr = (u32 *)0xE0000300;
*ptr = 0x1234;
*ptr = *ptr & 0xFF;

 

<컴파일러 최적화>

u32 *ptr = (u32 *)0xE0000300;
*ptr = 0x1234 & 0xFF;

 

최적화를 방지하기 위해 다음과 같이 코드를 수정한다

volatile u32 *ptr = (u32 *)0xE0000300;

 

커널에서의 동적 메모리 관리

kmalloc()

디바이스 드라이버에서 많이 사용되며, 할당 속도가 빠르지만 할당 가능한 크기가 정해져 있다.

char *buff;

    buff = kmalloc(1024, GFP_KERNEL);
    if (buff != NULL)
    {
        ...
        free(buff);
    }
    else
    {
        printk("kmalloc error\n");
    }

 

kmalloc(size_t size, int flags)의 flags 매개 변수

  • GFP_KERNEL
    • 커널이 관리하는 메모리가 충분하지 않은 경우에는(min_free_pages보드 작은 경우) 디바이스 드라이버를 호출한 프로세스가 수행을 멈추고, 할당할 수 있을 때까지 잠든다.
    • 인터럽트 서비스에 사용할 때는 블로킹 특성 때문에 이 값을 사용하면 안된다.
  • GFP_ATOMIC
    • 할당 가능하면 무조건 할당하고, 없으면 즉시 NULL을 반환한다.
    • 잠드는 문제는 없지만 할당 실패에 대한 경우를 고려해야 한다.
  • GFP_DMA
    • 연속된 물리 메모리를 할당 받을 때 사용한다.
    • 물리적 공간이 여러 곳으로 나뉘어 있으면 DMA 컨트롤러는 사용할 수 없다.
  • GFP_USER or GFP_HIGHUSER
    • user 공간에 메모리를 할당할 때 사용하며, blocking 될 수 있다.

 

vmalloc(), vfree() 함수

  • 할당하려는 크기 외에는 매개변수를 주지 않는다.
  • ex) buff = vmalloc(1024);
  • kmalloc() 함수는 할당 크기가 제한되어 있지만, vmalloc() 함수는 가상 공간이 허용하는 한 크기 제한 없이 할당 받을 수 있다.
  • vmalloc()은 가상 메모리 관리 루틴이 수행되기 때문에 kmalloc() 할당 속도 보다 느리다.
  • vmalloc()은 인터럽트 서비스 함수 안에서는 사용할 수 없다.

 

__get_free_pages(), free_pages() 함수

  • 페이지 단위 할당 함수
  • 함수의 크기 단위는 PAGE_SIZE가 된다.
  • #include <linux/gfp.h>
buff = __get_free_pages(GFP_KERNEL, order);
...
free_pages(buff, order);

 

 

'Device Driver' 카테고리의 다른 글

리눅스 디바이스 모델  (0) 2023.08.08
Virtual Memory  (0) 2023.07.16
디바이스 드라이버 구현  (0) 2023.07.01
디바이스 드라이버 개요  (0) 2023.07.01