달력

5

« 2024/5 »

  • 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
2011. 10. 18. 15:20

페이지 얻기 OS이야기2011. 10. 18. 15:20

이제 커널이 어떻게 페이자나 영역 등을 사용해 메모리를 관리하는지 이했했다면, 커널 내에서 메모리르 할당하고 해제하기 위한 인터페이스를 살펴봐.

커널에는 메모리를 요청하기 위한 하나의 저수준 메커니즘과, 이것을 사용하는 여러 가지 인터페이스가 제공된다. 이들 인터페이스는 모두 페이지를 기본단위로 삼아 메모리를 할당하며 <linux/gfp.h>에 선언돼있다. 이중 가장 핵심적인 함수는 다음과 같다

http://lxr.linux.no/linux+v2.6.39.4/include/linux/gfp.h
struct page * alloc_pages(unsigned int gtp_mask, unsigned int order); 

이 함수는 2^order, 즉 1 << order 크기의 연속된 물리적 페이지들을 할당한 후, 그 첫 페이지의  page구조체 포인터를 리턴한다.러가 나는 경우엔 NULL을 리턴한다. gtp_mask는 머지?

한편 다음의 함수르르 이용하면 페이지의 논리적 주소를 얻을 수 있다.
void *page_address(struct page *page);

이 함수는 매개변수로 넘긴 물리적 페이지가 현재 포함되어 잇는 논리적 주소에 대한 포인터를 반환한다.
unsigned long __get_free_pages(unsigned int gtp_mask, unsigned int order); 

이 함수는 alloc_pages()와 동일한 역할을 하지만, 요청한 페이지들의 첫 페이지에 대한 논리적 주소르르 바로 반환한다는 점이 다르다. 페이지는 연속적으로 할당되므로, 다음 페이지는 첫번째 페이지 뒤에 바로 이어지게 된다.
오직, 하나의 페이지만 필요할 경우 다음과 같은 짧은 형태의 wrapper함수를 이용할 수 있다.
struct page *alloc_page(unsigned int gtp_mask);
unsigned long __get_free_page(unsigned int gtp_mask);
이 함수는 앞서 살펴본 함수들과 동일한 역할을 하며, 단지 order를 0으로 사용한다는 점만이 다르다.2^0 = 1페이지


0으로 초기화된 페이지 얻기
다음 함수를 이용한다.
unsigned long get_zeroed_page(unsigned int gfp_mask);

이 함수는 __get_free_page()와 동일한 역할을 하지만, 페이지를 할당한 후 0으로 채운다는 점이 다르다. 이 함수는 유저 공간으로 넘겨지는 페이지에 대해 유용하게 사용할 수 있는데, 즉 할당된 페이지의 쓰레기 데이터가 종종 어떤 민감한 ㅌ데이터를 담고 있는 경우가 있기 때문이다. 시스템의 보안 유지를 위해, 유저 공간으로 넘겨지는 모든 페이지는 0으로 채우는 등의 방법을 사용하여 초기화되어야 한다. 
다음 표는 저수준 페이지 할당 함수들의 목록이다.
 함수  설명
struct page *alloc_page(gtp_mask)  하나의 페이지를 할당하여 해당 page구조체의 포인터를 리턴 
struct page * alloc_pages(gftp_mask, order) 2^order개의 페이지를 할당하고 첫번째 페이지의 구조체를 리턴 
 unsigned long __get_free_page(gtp_mask) 하나의 페이지를 할당하고 페이지의 논리적 주소에 대한 포인터를 리턴 
 unsigned long __get_free_pages(gfp_mask, order) 2^order 페이지르르 할당하고 첫번째 페이지의 논리적 주소에 대한 포인터를 리턴 
 unsigned long get_zeroed_page(gfp_mask) 하나의 페이지를 할당하고 0으로 초기화한 후 페이지의 논리적 주소를 리턴 


페이지 해제하기
할당받은 페이지의 사용을 끝내고 해제하려면 다음의 함수를 사용한다.
void __free_pages(struct page *page, unsigned int order)
void free_pages(unsigned long addr, unsigned int order)
void free_page(unsigned long addr);

여기서 주의할 것은, 우리가 할당한 페이지만을 해제해야 한다는 점이다. 잘못된 struct page포인터나 논ㄴ리주소를 지정하거나, 잘못된 order값을 지정하면 커널의 메모리 주소가 엉망이 될 수 있다. 

예제)
unsigned long page;
page = __get_free_pages(GFP_KERNEL, 3);
if(!page)
    return -ENOMEM;

/* page는 이제 8개 연속된 페이지 중 첫번째 페이지의 주소이다 */
//do Something

free_pages(page, 3);
/* 이제 페이지는 해제되어있으며 'page'에 저장된 주소는 더 이상 사용할 수 없다 */

GFP_KERNEL 인자는 gfp_mask 플래그의 한 예이다. 

지금까지 다룬 저수준 페이지 함수는 물리적으로 연속된 페이지가 필요한 경우에, 특히 오직 하나의 페이지나 매우 큰 크기의 페이지 메모리가 필요한 경우에 유용하다. 더욱 일반적인 바이트 단위 할당을 위한 커널 함수는 바로 다음에서 살펴볼 kmalloc()이다.



























 

'OS이야기' 카테고리의 다른 글

kfree()  (1) 2011.10.19
kmalloc()  (0) 2011.10.19
영역(Zone)  (0) 2011.10.18
메모리 관리  (0) 2011.10.17
실행지연  (0) 2011.10.17
:
Posted by НooпeУ


Code Start Code End