ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 디바이스 드라이버 / 동적 메모리 할당
    Linux/Linux Device Driver 2020. 9. 1. 12:40

    kmalloc()

    연속된 물리 메모리를 연속된 가상 공간에 매핑하여 할당 받는다. 

    GFP_KERNEL 플래그는 kmalloc() 함수에서 사용하는 대표적인 인자값으로 동적 메모리 할당이 항상 성공하도록 요구한다. 이 값으로 kmalloc() 함수를 사용하면 커널이 관리하는 메모리가 충분하지 않을 경우에는 디바이스 드라이버를 호출한 프로세스가 수행을 멈추고, 동적 메모리를 할당할 수 있는 상태가 될 때까지 잠든다. 그러다 다른 프로세스에서 메모리를 반환해 커널이 동적 메모리를 할당할 수 있는 상태가 되면 깨어난다. 그래서 kmalloc() 함수를 인터럽트 서비스에서 사용할 때는 이 값을 사용하면 안된다.

    GFP_ATOMIC 플래그를 사용하는 경우 슬립되지 않으므로 인터럽트 핸들러에서도 사용될 수 있다.

     

    vmalloc()

    단편화되어 연속되지 않는 여러 개의 페이지들을 모아 연속된 가상 메모리 공간에 매핑하여 할당받는다. 그래서 할당 속도가 매우 느리다. 

    kmalloc() 함수는 할당 크기가 제한되어 있지만, vmalloc() 함수는 가상 공간이 허용하는한 크기 제한 없이 할당받을 수 있다. 그래서 큰 메모리 공간을 할당할 때 주로 사용한다. 슬립될 수 있으므로 인터럽트 핸들러에서 사용되면 안된다.

     

    __get_free_pages()

    kmalloc() 함수나 vmalloc() 함수는 지정한 크기만큼 할당한다. 물론 PAGE_SIZE 단위로 할당되기 때문에 PAGE_SIZE 단위로 나누어 떨어지지 않으면 더 큰 공간을 할당할 수 있다. __get_free_pages() 함수류는 페이지 단위 할당 함수를 제공한다. 결국 별 차이 없는거 같다..

     

     

     

    응용프로그램에서 malloc() 함수를 이용하여 메모리를 할당할 경우 가상 메모리 기법에 의해 처리되기 때문에 실패할 가능성이 거의 없다. 그러나 디바이스 드라이버에서 메모리를 할당할 경우에는 메모리가 부족한 경우가 발생한다. 그럼 메모리 할당을 실패하게 되거나 슬립이되는데 이 와 같은 특성과 상황에 맞게 메모리 할당을 해줘야 한다.

     

     

    시스템이 대용량의 데이터를 처리하다 보면 커널 내부의 사용 가능한 메모리가 순간적으로 부족해진다. 보통 이런 경우에는 가상 파일 시스템이 동작하지만, 그 처리 속도가 매우 느리고 프로세스가 할당받은 메모리에 대해서만 적용할 수 있다. 그러나 시스템이 원할하게 동작하기 위해서는 프로세스 문맥이 아닌 커널의 인터럽트 서비스 함수 내부나 디바이스 드라이버 함수에서 요청한 메모리 할당을 처리하는 것도 중요하다 그래서 미리 할당하고, 관리하는 새로운 방식인 메모리 풀이라는 개념이 있다.

     

     

     

    pi@raspberrypi:~/Documents/malloc $ nano malloc.c

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/slab.h>
    #include <linux/vmalloc.h>
    
    void kmalloc_test(void)
    {
       char* buff;
    
       printk("kmalloc test\n");
    
       buff = kmalloc(32 * PAGE_SIZE, GFP_KERNEL);
    
       if(buff != NULL)
       {
          sprintf(buff, "kmalloc test ok\n");
          printk(buff);
          kfree(buff);
       }
    }
    
    void vmalloc_test(void)
    {
       char* buff;
    
       printk("vmalloc test\n");
    
       buff = vmalloc(33 * PAGE_SIZE);
    
       if(buff != NULL)
       {
          sprintf(buff, "vmalloc test ok\n");
          printk(buff);
          vfree(buff);
       }
    }
    
    void get_free_pages_test(void)
    {
       char* buff;
       int order;
    
       printk("__get_free_pages test\n");
    
       order = get_order(8192 * 10);
    
       buff = (char *) __get_free_pages(GFP_KERNEL, order);
    
       if(buff != NULL)
       {
          sprintf(buff, "__get_free_pages test ok [%d]\n", order);
          printk(buff);
          free_pages((unsigned long) buff, order);
       }
    }
    
    int memtest_init(void)
    {
       printk("module memory test start\n");
    
       kmalloc_test();
       vmalloc_test();
       get_free_pages_test();
    
       return 0;
    }
    
    void memtest_exit(void)
    {
       printk("module memory test end\n");
    }
    
    module_init(memtest_init);
    module_exit(memtest_exit);
    
    MODULE_AUTHOR("icjk1003@gmail.com");
    MODULE_LICENSE("GPL");

     

     

     

    pi@raspberrypi:~/Documents/kmalloc $ nano Makefile

    obj-m := malloc.o
    KDIR := /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)
    
    default:
          make -C $(KDIR) M=$(PWD) modules
    clean:
          make -C $(KDIR) M=$(PWD) clean

     

    pi@raspberrypi:~/Documents/malloc $ make

    pi@raspberrypi:~/Documents/malloc $ lsmod

    pi@raspberrypi:~/Documents/malloc $ sudo insmod malloc.ko

    pi@raspberrypi:~/Documents/malloc $ lsmod

    pi@raspberrypi:~/Documents/malloc $ dmesg

    pi@raspberrypi:~/Documents/malloc $ sudo rmmod malloc

     

    module memory test Start

    kmalloc test

    kmalloc test ok

    vmalloc test

    vmalloc test ok

    __get_free_pages test

    __get_free_pages test ok [5]

    module memory test end

     

    성공..

    댓글

Designed by Tistory.