13.07.2015 Views

Linux Module Programming - dmclab.hanyang.ac.kr

Linux Module Programming - dmclab.hanyang.ac.kr

Linux Module Programming - dmclab.hanyang.ac.kr

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Linux</strong> <strong>Module</strong> <strong>Programming</strong>• 모듈에 대한 이해• 모듈 프로그래밍• 모듈 빌드• 모듈 적재 및 제거


Understanding <strong>Linux</strong> <strong>Module</strong>• 모듈 프로그램의 장점• 효과적인 메모리 사용• Kernel 전체를 다시 컴파일 하지 않고,Kernel의 일부분 또는 디바이스 드라이버를 교체할 수 있다• 모듈 프로그램의 단점• Namesp<strong>ac</strong>e pollution• Kernel 에 삽입되어 확장된 Kernel이 되기에, 모듈을 개발 시 기존global variable, function name의 파악이 어려워 이들과의 충돌이발생하기 쉽다


<strong>Module</strong> <strong>Programming</strong>• Entry• Exit• 모듈이 로드될 때 불리는 초기화 함수• 성공적으로 로드 시 0, 그렇지 않은 경우 0이 아닌 값 리턴• Prototype : int init_func_name (void)• 모듈이 메모리에서 제거될 때 호출되는 해제 함수• 모듈이 반환되기 이전에 자원을 반납하거나 하드웨어가 일관 된 상태를유지하도록 하는 등의 일 처리함• Prototype : void exit_func_name (void)일반적으로 static으로 선언하여 구현한다.


<strong>Module</strong> <strong>Programming</strong>• MACRO (linux/init.h)• module_init()• #define module_init(initfn) \• static inline initcall_t __inittest(void) \• { return initfn; } \• int init_module(void) __attribute__((alias(#initfn)));


<strong>Module</strong> <strong>Programming</strong>• MACRO (linux/init.h)• module_exit()• #define module_exit(exitfn) \• static inline exitcall_t __exittest(void) \• { return exitfn; } \• void cleanup_module(void) __attribute__((alias(#exitfn)));


<strong>Module</strong> <strong>Programming</strong>• <strong>Module</strong> link concept (linux/module.h)• extern int init_module(void);• extern void cleanup_module(void);• These are either module local, or the kernel's dummy ones.


<strong>Module</strong> <strong>Programming</strong>• <strong>Module</strong> link conceptinsmodinit_module()register_capability()capabilities()……printk()rmmodcleanup_module()unregister_capability()


<strong>Module</strong> <strong>Programming</strong>• MACRO (include/linux/module.h)• MODULE_LICENSE• 모듈의 라이센스 정보 등록• 일반적으로 GPL을 사용하며, GPL이 아닌 모듈의 경우에 GPL만의심볼들을 사용할 수 없다• MODULE_AUTHOR• 모듈의 작성자 표시


<strong>Module</strong> <strong>Programming</strong>• printk() function (linux/kernel.h)• Kernel 에서 사용되는 printf()와 같은 용도의 함수• syslog에 메시지 추가 (etc/syslog.conf에서 설정)• dmesg utility를 사용하여 메시지 확인• 부동 소수점을 출력하지 못함• 메시지의 우선 순위 결정 매크로


<strong>Module</strong> Build• Simple module program (code)/* hello.c */#include #include #include static int hello_init(void){printk(KERN_ALERT "I bear a charmed life.\n");return 0;}static void hello_exit(void){printk(KERN_ALERT "Out, out, brief candle!\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR(“Jongmin Gim");


<strong>Module</strong> Build• Simple module program (makefile)O_TARGETobj-mKERNEL_DIRMODULE_DIRPWD:= hello.ko:= hello.o:= /lib/modules/$(shell uname -r)/build:= /lib/modules/$(shell uname -r)/kernel/hello_module:= $(shell pwd)default :install :clean :$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modulesmkdir -p $(MODULE_DIR)cp -f $(O_TARGET) $(MODULE_DIR)$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) clean


Loading and Executing <strong>Module</strong>• 모듈 명령어 요약명령어 용 도insmodrmmodlsmoddepmodmodprobemodinfomodule 설치 (install)실행중인 modules 제거 (unload)Load 된 module 들의 정보 표시커널 내부에 적재된 모듈간의 의존성 검사모듈간 의존성을 검사하여 누락된 다른 모듈을 찾아 적재함목적 파일을 검사하여 관련 정보 표시


Loading and Executing <strong>Module</strong>• 모듈 정보 확인


Loading and Executing <strong>Module</strong>• Error : Invalid module format• Kernel 과 module의 버전이 동일하지 않는 경우 발생


<strong>Module</strong> programming with kernel modification§ Export symbol*** include/linux/module.h:#define EXPORT_SYMBOL(sym)\__EXPORT_SYMBOL(sym, "")*** include/linux/module.h:#define __EXPORT_SYMBOL(sym, sec) \extern typeof(sym) sym; \__CRC_SYMBOL(sym, sec) \static const char __kstrtab_##sym[] \__attribute__((section("__ksymtab_strings"), aligned(1))) \= MODULE_SYMBOL_PREFIX #sym; \static const struct kernel_symbol __ksymtab_##sym \__used \__attribute__((section("___ksymtab" sec "+" #sym), unused)) \= { (unsigned long)&sym, __kstrtab_##sym }17


Example…void **sys_call_table = (void **)0x0xc057c150;//or extern void*sys_call_table[];asmlinkage int (*orig_task_print)(void); //기존 함수 백업용asmlinkage int new_task_print (void) //새로운 함수 내용{printk( KERN_ALERT “System Call Overide\n" );return orig_task_print (void);}int __init m_init( void ){orig_setuid = sys_call_table[__NR_task_print ]; //기존 함수의 주소 백업write_cr0( read_cr0( ) & ( ~0x10000 ) );sys_call_table[__NR_task_print] = new_task_print; //새로운 함수로 내용 변경write_cr0( read_cr0( ) | 0x10000 );printk( KERN_ALERT "<strong>Module</strong> init\n" );return 0;}void __exit m_exit( void ){write_cr0( read_cr0( ) & ( ~0x10000 ) );sys_call_table[__NR_task_print ] = orig_task_print; //원래 함수의 내용으로 복구write_cr0( read_cr0( ) | 0x10000 );printk( KERN_ALERT "<strong>Module</strong> exit\n" );}…18


모듈 코드• 모듈 컴파일 후 모듈 로딩# insmod module.ko• 테스트 코드 실행19


module_param (Kernel 3.2.15)*** include/linux/moduleparam.h:#define module_param(name, type, perm) \module_param_named(name, name, type, perm)#define module_param_named(name, value, type, perm) \param_check_##type(name, &(value)); \module_param_cb(name, &param_ops_##type, &value, perm); \__MODULE_PARM_TYPE(name, #type)#define module_param_cb(name, ops, arg, perm) \__module_param_call(MODULE_PARAM_PREFIX, \name, ops, arg, __same_type((arg), bool *), perm)#define __module_param_call(prefix, name, ops, arg, isbool, perm) \/* Default value instead of permissions? */ \static int __param_perm_check_##name __attribute__((unused)) = \BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \+ BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN); \static const char __param_str_##name[] = prefix #name; \static struct kernel_param __moduleparam_const __param_##name \__used \__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \= { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0, \{ arg } }20


module_param (Kernel 3.2.15)#include #include #include #include static int esos_get_num=0;module_param(esos_get_num,int,0);static int hello_init(void){printk(" Hello <strong>Module</strong> <strong>Programming</strong>: num is %d \n", esos_get_num);return 0;}static void hello_exit(void){printk(KERN_ALERT "Goodbye <strong>Module</strong> <strong>Programming</strong> \n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Jongmin Gim");21


module_param (Kernel 3.2.15)Build hello.ko moduleO_TARGETobj-mKERNEL_DIRMODULE_DIRPWD:= hello.ko:= hello.o:= /lib/modules/$(shell uname -r)/build:= /lib/modules/$(shell uname -r)/kernel/hello_module:= $(shell pwd)default :install :clean :$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modulesmkdir -p $(MODULE_DIR)cp -f $(O_TARGET) $(MODULE_DIR)$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) clean22


module_param (Kernel 3.2.15)• How to use it?• Insmod hello.ko esos_get_num=10• The parameters should be contiquous between left and right value.23


Q & Agim.jongmin@gmail.com24

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!