공유메모리 int shmget(key_t key, size_t size, int permflags); - size : 공유할 메모리 영역의 필요한 최소 크기를 바이트 단위로 표시 - IPC_CREAT | IPC_EXCL int *shmat(int shmid, const void *daddr, int shmflags); daddr * NULL : 시스템의 의해 결정 shmflags SHM_RDONLY, SHM_RND
공유메모리 int shmctl (int shmid, int command, struct shmid_ds *shmstat); -command : IPC_STAT, IPC_SET, IPC_RMID (예제) – test1.c (p288)
공유메모리 (실습) shmcpy를 수정 - 3개의 자식 프로세스를 생성하여 자식 0는 0~63, 1은 64~127, 2는 128~191을 공유메모리에 넣는 프로그램을 작성. 공유 메모리에 넣을 때 P, V를 실행시킨다. (실습) 위 프로그램을 message queue로 수정함 - 자식 0가 0~63을 부모에게 보내면 부모를 이를 화면으로 출력 - 자식 1이 64~127을 부모에게 보내서 부모가 이를 화면으로 출력 - 자식 2가 128~191을 부모에게 보내서 부모가 이를 화면으로 출력
커널 컴파일 버전 커널 컴파일 과정 커널 2.4 Loadable module support ----- > [*] Enable loadable module support [*] Set version information on all module symbols [*] Kernel module loader 커널 2.6 [*] module unloading [*] Forced module unloading [*] Module versioning support (EXPERIMENTAL) [*] Automatic kernel module loading
디바이스 파일(1)
디바이스 파일(2) mknod 명령 디바이스 파일 생성 mknod [디바이스 파일명] [파일 형] [주 번호] [부 번호] mknod /dev/devfile c 240 1 디바이스 드라이버 탐색 실질적인 디바이스 탐색
모듈 유틸리티 insmod rmmod lsmod 모듈을 커널에 적재한다. 커널에 등록된 모듈을 제거한다. 커널에 등록된 모듈의 상태를 보여준다.
모듈 소스 형식(1) 헤더 파일 선언 모듈 초기화 함수, 제거 함수 커널 2.6 #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> 커널 2.6 module_init(hello_init); module_exit(hello_exit);
모듈 컴파일용 Makefile obj-m := test.o // 모듈로 생성할 이름 지정 KDIR := /lib/modules/$(shell uname -r)/build // 커널의 소스 위치 지정 PWD := $(shell pwd) // 컴파일 대상의 모듈 소스의 위치 default: // 모듈을 컴파일하는 명령 지정 $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: // 컴파일 결과로 생성된 파일을 모 rm -rf *.ko // 두 지운다. rm -rf *.mod.* rm -rf .*.cmd rm -rf *.o
모듈 프로그램 맛보기(1) test.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> static int hello_init(void) { printk("Hello, world \n"); return 0; } static void hello_exit(void) printk("Goodbye, world\n"); module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("Dual BSD/GPL");
모듈 프로그램 맛보기(2) Makefile obj-m := test.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -rf *.ko rm -rf *.mod.* rm -rf .*.cmd rm -rf *.o
모듈 프로그램 맛보기(3)
모듈 프로그램 맛보기(4)
모듈 프로그램 맛보기(5)
이식성과 데이터형 서로 다른 프로세서 상에서의 이식성을 위해 가급적 리눅스 커널이 제공하는 데이터형을 사용하는 것이 좋다. #include <asm/types.h>에 정의. 주로 사용되는 데이터형 App Kernel __s8 s8 부호있는 8비트 정수형 __u8 u8 부호없는 __s16 s16 16비트 정수형 __u16 u16 __s32 s32 32비트 정수형 __u32 u32 __s64 s64 64비트 정수형 __u64 u64
동적 메모리 할당 함수 할당 속도가 빠르고 사용법이 간단해 kmalloc() 디바이스 드라이버에서 가장 많이 kfree() 사용되는 함수(할당 크기 제한 있음). vmalloc() vfree() 가상공간이 허용하는 한 크기 제한 없이 할당 받을 수 있다. 큰 메모리 공간을 할당할 때 주로 사용한다(속도가 느리다). __get_free_pages() __free_pages() 잘 사용되지 않는 함수.
kmalloc(), kfree()-1 메모리주소 kmalloc(할당 받을 크기, 옵션); kfree(메모리주소); * 할당 가능한 최대 크기는 32 x PAGE_SIZE (일반적으로 128KB) #include <linux/slab.h> char *buf; buf = kmalloc(1024, GFP_KERNEL); if (buf != NULL) { … kfree(buf); }
kmalloc(), kfree()-2 메모리 할당 시 사용되는 옵션 (할당된 메모리에 특성을 주거나 할당 시점에 처리방식을 지정) GFP_KERNEL 동적 메모리 할당이 항상 성공하도록 요구한다. 메모리 부족 시 메모리가 사용 가능해 질 때까지 잠든다. 이런 특성으로 인해서 인터럽트에서는 사용하면 안 된다. GFP_ATOMIC 커널에 할당 가능한 메모리가 있으면 무조건 할당하고, 없으면 즉시 NULL을 반환한다. 프로세스가 잠드는 문제는 없지만 메모리 할당에 실패할 경우를 항상 염두 해 두어야 한다. GFP_DMA 연속된 물리 메모리를 할당 받을 때 사용한다. (DMA를 사용할 때 사용해야 한다.)
vmalloc(), vfree() 메모리주소 vmalloc(할당 받을 크기); vfree(메모리주소); #include <linux/vmalloc.h> char *buf; buf = vmalloc(1024); if (buf != NULL) { … vfree(buf); }
vmalloc(), vfree() 특징 가상 주소 공간에서 할당받기 때문에 해당주소의 영역이 하드디스크에 있을 수도 있어 실패할 수 있다. 커다란 연속된 공간을 할당하기 위해 가상메모리 관리 루틴이 수행되기 때문에 kmalloc() 보다 속도가 매우 느리다. 할당 시 프로세스가 잠들지 못하게 할 수 없기 때문에 인터럽트 서비스 함수 안에서는 사용할 수 없다.
__get_free_pages(), free_pages() #include <linux/mm.h> //2.4 #include <linux/gfp.h> //2.6 #include <asm/page.h> //get_order char *buf; buf = __get_free_pages(GFP_KERNEL, order); /* order=0이면 1개의 page, order=3이면 3개의 page /* MAX_ORDER은 11, 그러나 5이하의 값만 사용하는 것이 안전 (32*PAGE_SIZE) */ if (buf != NULL) { … free_pages(buf, order); }