User Space와 Kernel Space
응용 프로그램은 유저 영역에서, 커널 모듈은 커널 영역에서 실행 됨.
이와 같이 메모리 영역을 나눔으로서 응용 프로그램이 OS가 load되어 있는 커널 영역에 침범하여 시스템에 critical한 에러 등을 발생시키는 일을 방지.
커널 영역에 접근하기 위해서는 커널 모드(or 관리자 모드)로 전환되어야 함
System Call(시스템 콜)
위와 같은 이유로 인해 응용 프로그램에서 H/W나 커널의 리소스에 접근하여 사용할 수 있도록 System Call 방식을 이용
응용프로그램이 직접 커널의 기능을 호출할 수 없으므로 커널은 유저공간에 추상화된 인터페이스인 System Call을 제공하며 이를 통해 유저 영역에서 커널 기능을 호출.
시스템 콜이 호출 되면 유저 모드에서 커널 모드로 진입해야하는데 이때 SW IRQ가 발생하여 시스템은 커널 모드로 전환되고 시스템 콜 handler가 실행되어 유저 영역에서 요청한 기능을 수행함.
이를 통해 시스템의 보안과 안정성을 제공할 수 있음.
ex) open() 호출 과정
- main()에서 open() 호출
- libc에 구현된 open()이 호출되면 SWI(SW Interrupt)가 발생하여 Vector table을 참조하여 해당 IRQ에 해당하는 ISR호출(vector_swi)
- ISR vector_swi()에서 해당 시스템 콜 번호에 해당하는 VFS의 sys_open() 함수 호출
- VFS(가상 파일 시스템)에 등록된 dev_open()호출
- 실제 dev_open()에서 커널영역에서 작업 수행
유저 공간 메모리와 커널 공간 메모리의 특성
유저 공간 메모리
표준 library인 libc의 malloc() / free()를 통해 메모리를 할당 받고 해제함.
이때 libc는 시스템 콜을 이용해서 커널의 기능을 통해 메모리를 할당 받고 해제하는 내용이 구현되어 있음.
커널 공간 메모리
커널은 paging 기법이라고 하는 메모리 할당 기법을 사용하는데 대개 4kb 단위를 사용.
시스템의 가용 메모리가 없을 경우 paging기법을 사용하지 않고 메모리를 할당 받을 수 있음.
커널에서의 동적 메모리 할당 함수
kmalloc()
커널 영역에서 연속된 메모리를 할당. 할당속도가 빠름
kmalloc()로 메모리를 할당 받을 때에는 할당 가능한 크기가 정해져 있음
#include <linux/slab.h>
char *buff;
buff = kmalloc(1024, GFP_KERNEL);
if(buff == NULL)
printk("kmalloc() err!\n");
free(buff)
|
kmalloc() 사용 시 flags 매개 변수
- GFP_KERNEL: 커널이 관리하는 메모리가 충분하지 않은 경우 디바이스 드라이버를 호출한 프로세스는 수행을 멈추고 할당할 수 있을 때까지 sleep 상태. ISR 등을 처리할 때에는 blocking 특성 때문에 해당 flag를 사용하면 안됨
- GFP_ATOMIC: 할당 가능하면 할당하고, 할당이 불가능 하면 즉시 NULL 리턴, sleep에 빠지지는 않지만 할당 실패를 고려해야 함.
- GFP_DMA: DMA 컨트롤러에서 사용하기 위해 메모리를 물리적으로 연속되도록 할당 받을 때 사용, 물리적 공간이 여러 곳으로 분산되어 있으면 DMA 컨트롤러는 사용할 수 없음.
- GFP_USER or GFP_HIGHUSER: 유저 영역에 메모리를 할당할 때 사용하며 blocking될 수 있음.
-> kzalloc()의 경우 kmalloc()과 거의 유사한 기능을 수행하나, 내부적으로 __GFP_ZERO flag가 적용되어 할당된 메모리를 모두 0으로 초기화 한다.(memset 필요 없음)
vmalloc()
여려 page 메모리를 연속적인 것처럼(linear) 할당 하여 가상 메모리 체계에서는 연속적인 메모리처럼 할당
큰 메모리 공간이 필요할 때 사용하지만 할당 속도가 느림(분산된 메모리를 연속적으로 처리하는 가상 메모리 관리 때문)
느린 할당 속도 때문에 ISR(Interrupt Service Routine)에서는 사용 불가
하기와 같이 vmalloc의 인자로 할당할 크기만 전달
#include <linux/slab.h>
char *buff;
buff = vmalloc(1024);
if(buff == NULL)
printk("vmalloc() err!\n");
free(buff)
|
__get_free_pages(), free_pages()
페이지 단위로 메모리를 할당 받기 위해 사용하는 함수. 할당 받으려는 page 단위 수를 위해 get_order()라고 하는 매크로를 사용.
__get_free_pages() 예시
#include <linux/gfp.h>
/* gfp.h에 선언된 __get_free_pages(), free_pages() 함수
unsigned long FASTCALL(__get_free_pages(unsigned int gfp_mask, unsigned int order));
void FASTCALL(free_pages(unsigned long addr, unsigned int order));
*/
char *buff;
int order;
order = get_order(8192);
buff = __get_free_page(GFP_KERNEL, order);
if(buff == NULL)
printk("__get_free_page() err!\n");
free_pages(buff)
|
'Linux System > Linux Kernel' 카테고리의 다른 글
[Kernel] Timer (0) | 2023.02.11 |
---|---|
runtime에 target board kernel의 config 확인 (0) | 2022.09.14 |
Device Driver - Atomic (0) | 2022.05.23 |
Kernel Build (0) | 2022.03.03 |
Kernel Source Tree (0) | 2022.03.03 |