Chapter 2. Building and Running Modules 간단한 코드 예 커널 모듈 자원의 이용 자동 및 수동 설정 skull 코드 예 순천향대학교 정보기술공학부 이 상 정 1
간단한 예 순천향대학교 정보기술공학부 이 상 정 2
hello.c #define MODULE #include <linux/module.h> int init_module(void) { printk("<1>Hello, world\n"); return 0; } void cleanup_module(void) { printk("<1>Goodbye cruel world\n"); } # gcc -c hello.c # /sbin/insmod ./hello.o # /sbin/rmmod hello # tail /var/log/messages 순천향대학교 정보기술공학부 이 상 정 3
코드 설명 모듈 등록 및 해제 예제 코드 printk() 함수 등록 시 init_module() 실행 해제 시 cleanup_modue() 실행 예제 코드 insmod로 모듈을 로드하고 커널에 링크된 후 printk()를 호출 rmmod로 모듈을 제거할 때도 printk()를 호출 printk() 함수 리눅스 커널은 C 라이브러리 없이 자체 고유의 함수 지원 따라서 printf()는 지원되지 않고 비슷한 기능의 printk() 함수 지원 <1>은 메시지의 우선순위를 나타내며 번호가 낮을수록 우선순위가 높음 콘솔에서 실행된 경우 화면에 출력되고 xterm 등에서는 /var/log/messages 등과 같은 시스템 로그 파일에 출력 순천향대학교 정보기술공학부 이 상 정 4
명시적 초기화 및 해제 함수 명시적인 초기화와 클린업 함수 커널 2.3.13 부터는 init_module, cleaup_module 대신 임의의 함수 이름 명시 가능 다음과 같이 my_init, my_cleanup 과 같은 다른 이름을 명시적으로 지정 #include <linux/init.h> module_init(my_init); module_exit(my_cleanup); 순천향대학교 정보기술공학부 이 상 정 5
순천향대학교 정보기술공학부 이 상 정 6
커널 모듈 순천향대학교 정보기술공학부 이 상 정 7
커널 헤더 파일과 심볼 커널 헤더 파일 커널 심볼의 이름 커널은 어떤 라이브러리도 사용하지 않으므로 커널 헤더파일만 삽입하여 사용 커널 헤더 파일은 커널 소스의 include/linux, include/asm 에 위치 대개 커널 소스는 /usr/src/linux/ 에 위치 커널 심볼의 이름 아무리 작은 모듈이라도 전체 커널에 연결되어 사용되므로 심볼들의 이름이 중복되지 않도록 주의 심볼들을 static으로 선언하거나 고유의 prefix를 부여하여 에러를 피함 순천향대학교 정보기술공학부 이 상 정 8
사용자 영역과 커널 영역 프로그램은 커널 영역(kernel space, 또는 supervisor mode)와 사용자 영역(user space)로 구분되어 동작 각 영역은 다른 우선순위를 갖고 각기 고유의 메모리 매핑(주소영역)을 가짐 유닉스는 응용 프로그램이 시스템 콜을 호출하거나 하드웨어 인터럽트에 의해 중단 될 떄 마다 사용자 영역에서 커널 영역으로 전환 시스템 콜을 실행하는 커널 코드는 프로세스의 문맥(context) 안에서 동작 반면에 인터럽트를 처리하는 코드는 프로세스에 비동기적이고 특정 프로세스와 무관 모듈은 커널의 기능을 확장하는 역할 모듈 코드는 커널 영역에서 수행 일반적으로 드라이버는 앞에서 언급한 두 가지 형태의 코드를 수행 모듈의 일부 함수는 시스템 콜의 부분으로 수행되고, 일부는 인터럽트 처리 영역 안에 존재 순천향대학교 정보기술공학부 이 상 정 9
커널의 병행성(concurrency) (1) 응용 프로그램들은 동일한 수행환경 조건 하에서 순서적으로 실행 커널 프로그래밍에서는 동시에 많은 상황의 변화발생 리눅스 시스템은 다수의 프로세서들이 실행되어 이들이 동시에 드라이버의 사용을 시도 대부분의 디바이스들이 드라이버가 실행 중에 동시에 인터럽트를 유발하여 처리루틴을 실행 SMP(symmetric multiprocessor)인 경우에는 드라이버가 여러 CPU에서 동시에 실행 드라이버 코드를 포함한 리눅스 커널 코드는 재진입(reentrant) 가능해야 함 프로그램이 동시에 여러 문맥를 실행할 수 있어야 함을 의미 실행되는 쓰레드들이 분리되도록 자료구조를 설계해야 하고, 데이터를 파괴하지 않도록 공유 데이터의 접근에 주의 순천향대학교 정보기술공학부 이 상 정 10
커널의 병행성(concurrency) (2) 일반적으로 리눅스 코드는 비선점형(nonpreemptive) 실행 중인 커널 코드(시스템 콜)가 정상적으로 종료되지 않는 한 예외 처리 등에 프로세서의 점유를 양보하지 않음 단일 프로세서 시스템에서는 커널의 코드들이 블록(block, sleep) 되지 않는다면 동시에 실행되는 병행성을 방지할 수 있음 SMP 시스템에서는 비선점형이라도 프로그램이 동시에 실행되어 문제 향 후 커널이 선점형(preemptive)으로 전환될 예정 커널 2.6은 선점형으로 설계 단일 프로세서에서도 병행성을 고려해야 함 순천향대학교 정보기술공학부 이 상 정 11
커널 심볼 테이블 모듈 스택킹 (module stacking) mdprobe 명령 심볼 관련 매크로 모듈이 로드될 때 이 모듈에 의해 export된 심볼들은 커널 심볼 테이블에 포함되고 스택(stacking)되어 다른 모듈들이 이 심볼 사용 가능 심볼들은 /proc/ksyms 나 ksyms 명령으로 조회 mdprobe 명령 insmod와 유사하고 다른 점은 로드하고자 하는 모듈이 필요하는 다른 모듈들도 함께 로드 심볼 관련 매크로 EXPORT_NO_SYMBOLS 어떤 심볼도 export 하지 않음 EXPORT_SYMTAB 심볼들의 일부를 export 순천향대학교 정보기술공학부 이 상 정 12
병렬포트 스택킹 예 순천향대학교 정보기술공학부 이 상 정 13
사용빈도(usage count) 시스템은 각 모듈에 대한 사용빈도를 관리 사용빈도를 위해 다음의 매크로가 사용 모듈이 현재 사용 중인지를 체크 모듈이 사용 중인 경우에는 모듈을 해제(unload)할 수 없음 사용빈도를 위해 다음의 매크로가 사용 MOD_INC_USE_COUNT : 현재 모듈의 사용빈도를 증가 MOD_DEC_USE_COUNT : 사용빈도를 감소 MOD_IN_USE : 사용빈도가 0이 아니면 참 /proc/modules 는 현재 로드된 모듈의 정보 디스플레이 이 파일은 아래 예와 같이 현재 로드된 모듈의 이름, 사용하는 메모리 바이트, 사용빈도를 디스플레이 parport_pc 7604 1 (autoclean) lp 4800 0 (unused) parport 8084 1 [parport_probe parport_pc lp] …………… 위 에서 병렬포트는 스택킹되고, (autoclean)은 모듈이 kmod 나 kerneld 에 의해 관리됨을 의미 순천향대학교 정보기술공학부 이 상 정 14
자원(resource)의 이용 순천향대학교 정보기술공학부 이 상 정 15
시스템 자원(system resource) 모듈은 메모리, I/O 포트, I/O 메모리(주변장치가 상주하는 메모리 영역), 인터럽트, DMA 채널 등과 같은 시스템 자원을 사용하여 태스크를 수행 I/O 포트와 I/O 메모리 드라이버의 전형적인 작업은 I/O 포트와 I/O 메모리(둘을 통합하여 I/O 영역(region)이라 한다)에 접근하여 읽기, 쓰기를 수행 디바이스 드라이버는 어느 경우에든 다른 드라이버와의 간섭을 방지하기 위해 자신의 I/O 영역의 독점적 접근을 보장해야 함 리눅스 개발자는 다른 디바이스 간 충돌을 방지하기 위해 I/O 영역을 요청/해제하는 방식을 개발해야 함 등록된 자원들에 관한 정보는 /proc/ioports, /proc/iomem 등의 파일에서 조회 순천향대학교 정보기술공학부 이 상 정 16
I/O 포트 다음은 /proc/ioports 의 일부 내용 예 0000-001f : dma1 0020-003f : pic1 0040-005f : timer 0060-006f : keyboard 0080-008f : dma page reg ……… 1000-103f : Intel Corporation 82371AB PIIX4 ACPI 1000-1003 : acpi 1004-1005 : acpi 1100-110f : Intel Corporation 82371AB PIIX4 IDE ………… 순천향대학교 정보기술공학부 이 상 정 17
I/O 포트 함수 다음 함수들이 I/O 포트를 조사하고 할당하는 함수 #include <linux/ioport.h> int check_region(unsigned long start, unsigned long len); struct resource *request_region(unsigned long start, unsigned long len, char *name); void release_region(unsigned long start, unsigned long len); check_region 함수는 포트가 가용한지를 조사하여 가용하지 않으면 음수를 반환 request_region은 포트의 영역을 할당하고 할당에 성공하면 non-NULL 포인터를 반환 release_region은 할당된 포트를 해제하는 함수 순천향대학교 정보기술공학부 이 상 정 18
skull 코드 예 skull(simple kernel utility for loading localities) 샘플 드라이버의 포트 등록/해제하는 코드 예 #include <linux/ioport.h> #include <linux/errno.h> static int skull_detect(unsigned int port, unsigned int range) { int err; if ((err = check_region(port,range)) < 0) return err; /* busy */ if (skull_probe_hw(port,range) != 0) return -ENODEV; /* not found */ request_region(port,range,"skull"); /* "Can't fail" */ return 0; } void skull_release(unsigned int port, unsigned int range) { release_region(port,range); } 순천향대학교 정보기술공학부 이 상 정 19
I/O 메모리 다음은 /proc/iomem 파일의 내용 예 00000000-0009fbff : System RAM 0009fc00-0009ffff : reserved 000a0000-000bffff : Video RAM area 000c0000-000c7fff : Video ROM 000f0000-000fffff : System ROM 00100000-03feffff : System RAM 00100000-0022c557 : Kernel code 0022c558-0024455f : Kernel data 20000000-2fffffff : Intel Corporation 440BX/ZX – 82443BX/ZX Host bridge ………… 순천향대학교 정보기술공학부 이 상 정 20
I/O 메모리 함수 I/O 메모리를 조사하고 할당하는 함수 int check_mem_region(unsigned long start, unsigned long len); int request_mem_region(unsigned long start, unsigned long len, char *name); int release_mem_region(unsigned long start, unsigned long len); 코드 예 if (check_mem_region(mem_addr, mem_size)) { printk("drivername:memory already in use\n"); return -EBUSY; } request_mem_region(mem_addr, mem_size, "drivername"); 순천향대학교 정보기술공학부 이 상 정 21
자동 및 수동 설정 순천향대학교 정보기술공학부 이 상 정 22
드라이버 파라미터 (1) 드라이버의 파라미터는 시스템에 따라 구성해주어야 하는데 명시적으로 지정하거나 자동으로 검출하여 지정 파라미터 값들은 insmod나 modprobe 를 사용하여 로드 시에 명시적으로 지정 skull_ival, skull_sval 파라미터를 지정하는 예 insmod skull skull_ival=666 skull_sval="the beast" MODULE_PARM 매크로 <linux/module.h>에 정의되어 모듈 파라미터를 명시적으로 지정 예 int skull_ival=0; char *skull_sval; MODULE_PARM (skull_ival, "i"); MODULE_PARM (skull_sval, "s"); 타입은 바이트 b, short s, 정수 i, long l, 문자열 s 가 있다. 순천향대학교 정보기술공학부 이 상 정 23
드라이버 파라미터 (2) MODULE_PARM_DESC 매크로 목적파일에 코멘트를 삽입하는 매크로 아래와 같이 배열(최소한 2-4개 값을 갖는 배열)을 지정할 수도 있다 int skull_array[4]; MODULE_PARM (skull_array, "2-4i"); MODULE_PARM_DESC 매크로 모듈 파라미터의 내용을 목적파일에 기술 기술된 내용은 objdump를 사용하여 확인 int base_port = 0x300; MODULE_PARM (base_port, "i"); MODULE_PARM_DESC (base_port, "The base I/O port (default 0x300)"); 목적파일에 코멘트를 삽입하는 매크로 MODULE_AUTHOR(name) : 목적파일에 개발자 이름 삽입 MODULE_DESCRIPTION(desc) : 목적파일에 모듈에 대해 기술 MODULE_SUPPORTED_DEVICE(dev) : 목적파일에 모듈에 의해 지원되는 디바이스 기술 순천향대학교 정보기술공학부 이 상 정 24
skull 포트주소 자동검출 코드 예 skull 포트주소 자동검출(autodetection) 코드 예 수동으로는 하나의 디바이스 조사만을 하는 코드 /* port ranges: the device can reside between * 0x280 and 0x300, in step of 0x10. It uses 0x10 ports. */ #define SKULL_PORT_FLOOR 0x280 #define SKULL_PORT_CEIL 0x300 #define SKULL_PORT_RANGE 0x010 /* the following function performs autodetection, unless a specific * value was assigned by insmod to "skull_port_base" */ static int skull_port_base=0; /* 0 forces autodetection */ MODULE_PARM (skull_port_base, "i"); MODULE_PARM_DESC (skull_port_base, "Base I/O port for skull"); 순천향대학교 정보기술공학부 이 상 정 25
skull 포트주소 자동검출 코드 예 static int skull_find_hw(void) /* returns the # of devices */ { /* base is either the load-time value or the first trial */ int base = skull_port_base ? skull_port_base : SKULL_PORT_FLOOR; int result = 0; /* loop one time if value assigned, try them all if autodetecting */ do { if (skull_detect(base, SKULL_PORT_RANGE) == 0) { skull_init_board(base); result++; } base += SKULL_PORT_RANGE; /* prepare for next trial */ } while (skull_port_base == 0 && base < SKULL_PORT_CEIL); return result; 순천향대학교 정보기술공학부 이 상 정 26
skull 코드 예 순천향대학교 정보기술공학부 이 상 정 27
skull 코드 skull(simple kernel utility for loading localities) 샘플 드라이버 I/O 메모리 영역 조사, 0xa0000 ~ 0x100000, 2K 단위 I/O 포트 할당, 0x280 ~ 0x300, 0x10 단위 , skull_port_base 파라미터를 지정하지 않으면 자동검출 과제 코드 분석: Makefile skull_init.c skull_clean.c 실행 및 결과분석 순천향대학교 정보기술공학부 이 상 정 28