커널 모듈


- 리눅스 커널은 유연성 향상을 위해 커널의 일부 기능을 모듈로 분리한 후 필요에 따라 커널에 결합하는 메커니즘 제공.


1. 커널 기능을 모듈로 구현하면 기능 수정이나 추가 용의.

2. 커널과 분리된 별도의 개발 진행 가능.

3. 디바이스 드라이버도 적재 가능한 모듈의 한 종류.




커널 모듈 - 모듈 구현


- 커널 모듈 구현 형태.

1. 커널 소스 트리에 포함시켜 구현.

* 개별 또는 커널과 함께 선택 빌드 가능. --> make menuconfig

2. 커널 소스트리에서 분리해 별도의 프로젝트로 구현.


- 커널 모듈의 특징

1. 커널의 일부분이므로 커널 프로그램의 특징을 그대로 가짐.(커널코드사용)

2. 시스템 호출 테이블에 구현한 함수 주소를 정적으로 등록할 수 없음.

* 커널의 모든 심볼은 정적 주소를 갖지만 동적인 모듈은 변할 수 있음.(제거 가능하기 때문에)

* 모듈은 커널 영역에서 제거될 수 있으므로 항상 유효주소를 보장할 수 없음.

3. 응용프로그램처럼 배포하고 동적으로 커널 영역에 적재 및 제거 가능.


- 모듈 적재 및 제거

1. 모듈을 커널에 적재 및 제거하는 과정에서 사용자 정의 함수를 함께 실행 가능.

2. module_init()

* 모듈이 커널에 적재될 때 호출되는 사용자 함수 등록.

3. module_exit()

* 모듈이 커널에서 제거될 때 호출되는 사용자 등록 함수 등록.


- 모듈 정보

1. MODULE_LICENSE(): 모듈의 라이선스 기술

2. MODULE_DESCRIPTION(): 모듈에 대한 설명 기술

3. MODULE_AUTHOR(): 모듈에 대한 소유권 기술




- 모듈 프로그램 기본 구조.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
    
static int mod_hello_init(void)
{
    printk("%s\n", __FUNCTION__);
    
    return 0;
}
 
static void mod_hello_exit(void)
{
    printk("%s\n", __FUNCTION__);
}
 
module_init(mod_hello_init);
module_exit(mod_hello_exit);
 
MODULE_AUTHOR("PlanX Studio");
MODULE_DESCRIPTION("mod_hello");
MODULE_LICENSE("Dual BSD/GPL");
cs



- Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
obj-m := 파일이름.o        
 
#커널소스 디렉토리
KDIR := $(HOME)/linux
 
default:
    make -C $(KDIR) M=$(PWD) modules
        
clean :    
    rm -rf *.ko
    rm -rf *.mod.*
    rm -rf .*.cmd
    rm -rf *.o
    rm -rf *.symvers
    rm -rf *.order
    rm -rf .tmp_versions
cs



- 커널 모듈 적재 실습( target 에서 작업 )

1. $ sudo insmod 를 이용하여 [모듈명].ko 파일을 실행 시킨다.

2. $ lsmod 명령어를 이용하여 모듈이 실행되었는지 확인한다.






커널 모듈 - 모듈 관리 툴


- 리눅스는 모듈을 동적으로 적재하거나 제거하는데 필요한 관리 툴 제공.

1. 모듈은 파일시스템의 특정 디렉터리 경로에 위치.

* /lib/modules(일반 리눅스)

2. 모듈은 필요에 따라 커널 영역으로 적재하거나 제거할 수 있음.

* lsmod: 커널에 삽입된 모듈 목록 확인.

* insmod: 모듈 파일 이름(*.ko)을 이용해 커널에 적재

** 모듈이 적재될 때 module_init()로 등록한 사용자 함수 실행

* rmmod: 모둘 이름을 이용해 커널에서 제거.

** 모듈이 제거될 때 module_exit()로 등록한 사용자 함수 실행



- 모듈 적재 및 제거에 따른 실행 흐름

1. 모듈 적재

* insmod <path/module_name.ko>로 해당 모듈을 커널 영역에 적재.

** 모듈 파일에 대한 절대 또는 상대 경로 사용.

* 모듈이 커널에 적재되면 module_init()로 등록한 사용자 함수 실행.

* 해당 함수가 오류를 반환하면 모듈 적재는 실패함.

2. 모듈 제거

* rmmod <module_name>로 제거된 모듈 제거.

* 모듈이 제거되기 전에 module_exit()로 등록한 사용자 함수 실행.


<적재 및 제거 순서>

$insmod hello.ko --> load hello.ko --> module_init(hello_init)실행 --> hello_init()실행

--> $rmmod hello --> module_exit(hello_exit)실행 --> hello_exit() --> remove hello.ko









모듈 라이선스


- 라이선스 종류

1. MODULE_LICENSE() 매크로 함수 사용.

2. GPL, GPL v2

3. MIT/HPL, BSD/GPL, MPL/GPL

4. 기타 영리 라이선스.


- GPL 라이선스

1. GPL이 아닐 경우 참조하는 모듈 함수의 제한을 가하기 위한 것.

2. 독점적인 모듈에서 발생하는 문제점을 식별하기 위해 커널 개발자에 의해 사용.



- 오염(tainted) 플래그

1. GPL을 따르지 않는 모듈이 메모리에 적재되면 커널의 오염 플래그 설정.

2. 소스 코드가 공개되지 않는 모듈이 커널에 포함되어 있음을 의미.

* $cat /proc/sys/kerner/tainted 명령으로 오염 상태 확인

0이면 오염되지 않음


3. 오염 플래그 의미는 Documentation/sysctl/kernerl.txt에 기술되어 있음


* OR 연산자로 묶어서 제공.





모듈 컴파일


- 모듈 컴파일 구분

1. 처음부터 커널에 포함하는 정적 링크.

* 정적 링크는 커널 소스 트리에 모듈 구현이 포함되어 있을 때 선택.

* 모듈 정적 링크로 컴파일하면 zImage에 포함.

* zImage에 포함된 모듈을 타깃에 적용하려면 커널을 새로 설치.


2. 커널에서 분리하는 증분 링크

* 증분 링크는 소스 트리에서 분리해 별도의 프로젝트로 진행할 때 사용.

* 증분 링크로 컴파일하면 확장자가 .ko인 모듈 파일이 생성됨.

* 적재 가능한 모듈은 모듈 파일만 설치하면 되므로 유지보수가 훨씬 수월.

* 커널 소스 트리에 포함된 모듈 구현도 사용자 선택에 의해 증분 링크 가능.



- 모듈 컴파일

1. 커널 빌드 시스템을 이용해 컴파일

* 커널 소스트리에 분리된 별도의 프로젝트로 구현하더라도 커널 소스트리 필요.

* 모듈의 Makefile에는 커널 소스트리 경로 및 모듈 정보만 기술.

2. include/generated/autoconf.h 참조

* 커널 빌드 과정에서 .config를 참조해 자동 생성되며 커널 구성에 대한 매크로 상수 정의.

* 커널의 많은 소스 파일들이 #include로 이 파일 포함.

* 커널 모듈과 커널 빌드 시스템을 이용하므로 이 파일이 필요함

3. Module.symvers 또는 <해당 모듈 프로젝트>/Modules.symvers

* 다른 모듈에서 노출한 심볼을 사용하려면 빌드할 때 심볼 정보가 필요함.

* Modules.symvers : 커널에서 노출하는 심볼 정보.

* <해당 모듈 프로젝트>/Modules.symvers : 해당 모듈에서 노출하는 심볼 정보.

** 참조 모듈을 빌드할 때 KBUILD_EXTRA_SYMBOLS(Makefile)에 경로 할당 필요.

** 경로는 커널 소스트리를 기준으로 한 절대 경로 사용.



- 일반적인 모듈 Makefile

1. KBUILD_CFLAGS : 컴파일러에 전달할 옵션 기술

2. KBUILD_EXTRA_SYMBOLS : 외부 심볼 참조 경로 기술

* Module.symvers 파일 경로

3. MOD_NAME : 모듈 이름 기술 -> 동일한 이름의 소스 코드를 찾아 모듈 생성

4. KDIR : 호스트의 커널 소스 루트 경로 기술

5. make -C $(KDIR) M=$(shell pwd) modules : 독립 프로젝트 유형의 모듈 컴파일

* $(shell pwd) : 현재 모듈 소스 경로






커널 소스트리에 포함된 모듈 구현


- 커널 소스트리에서 작업.

1. 커널 구성에 따라 커널에 포함될 수도 있고, 모듈만 별도로 빌드해 동적으로 적재할 수 있음.

2. 커널 소스 트리 경로에서 필요한 모듈 구현.

3. 커널 빌드 시스템을 위해 Kconfig와 Makefile 파일 작성.

* 기존 Kconfig와 Makefile에 새로 작성한 Kconfig와 Makefile 정보 추가.

* 커널과 함께 컴파일 하도록 Makefile에 해당 모듈 컴파일 정보 포함.

* obj-m := <module_name>.o

* 커널과 분리해 컴파일할 수 있도록 Makefile에 추가 정보 기술.

* KDIR := ~/linux

* $(MAKE) -C $(KDIR) M=$(shell pwd) modules

* 범용 Makefile로 커널 포함 또는 분리된 컴파일에 상황에 대응.





커널 소스트리에서 분리된 모듈 구현


- 커널 소스트리에 분리된 별도의 프로젝트로 진행.

1. 응용프로그램 구현과 유사.

* 커널에 비해 유지보수가 쉬움

2. 모듈을 컴파일할 때 커널 API에 대한 헤더 및 심볼 정보 필요.

* 커널 빌드 시스템을 이용해 컴파일.

* 모듈은 커널 기능의 일부임.

* 단, V2.6부터는 커널의 모든 심볼에 자유롭게 접근할 수는 없음.

* 명시적으로 노출된 심볼만 접근 가능.

3. 커널 설정에 포함되지 않으므로 Kconfig를 작성할 필요 없음.

* Kconfig는 make menuconfig를 실행할 때 제공되는 정보.

* 사용자 선택에 따라 .config에 매크로 정의가 포함됨.

4. 항상 동적으로 커널 영역 적재.





모듈 심볼 노출


- 커널이나 모듈에서 정의한 심볼을 다른 모듈에서 사용.

1. 심볼은 전역 변수나 함수.

2. 각각 구현된 커널이나 모듈은 동일한 커널 영역에서 실행.

3. 커널은 하나의 프로그램 형태며 모듈도 커널의 일부분임.


- 심볼 접근 제한

1. 커널은 모듈에서 정의한 심볼에 접근할 수 없음.

* 모듈이 동적으로 적재될 수 있기 때문.

2. 별도의 노출 함수를 통해 접근 허용.

* 노출 함수와 모듈 라이선스에 의존.

* 커널은 모듈에서 해당 심볼에 접근할 수 있도록 별도의 노출 함수 사용.

* 모듈 역시 다른 모듈에서 해당 심볼에 접근할 수 있도록 노출 함수 사용.


- 심볼 노출

1. 커널 또는 모듈에서 정의한 심볼을 외부로 노출하면 다른 모듈에서 접근 가능.

2. EXPORT_SYMBOL()

* 모든 모듈에 심볼 노출

3. EXPORT_SYMBOL_GPL()

* GPL 라이선스 모듈에만 심볼 노출

4. 해당 모듈은 MODULE_LICENSE()에 따라 라이선스 결정.

* 생략하면 GPL 라이선스를 갖지 않는 모듈.


- 심볼 노출예

1. 커널에서 구현한 함수는 상호 호출 가능.

2. 커널에서는 모듈에서 구현한 함수에 접근할 수 없음.

3. 커널은 모듈을 위해 특정 함수를 노출할 수 있음.

4. 동일 모듈에서 구현한 함수는 상호 호출 가능.

5. 모듈은 라이선스 제한에 따라 커널이 노출한 함수에 접근할 수 있음.

6. 모듈은 다른 모듈을 위해 특정 함수를 노출할 수 있음.

7. 모듈은 라이선스 제한에 따라 다른 모듈이 노출한 함수를 호출할 수 있음.





- 모듈 심볼 노출(EXPORT) 예



- 모듈 심볼 노출(IMPORT) 예



- mod_symbol_export 에서 노출한 심볼 연결

1. 노출한 심볼 정보는 해당 프로젝트 경로의 Modules.symvers로 존재.

* 첫 번째 방법 : mod_symbol_export/Modules.symvers 파일 내용을 커널 소스트리 루트 경로의 Module.symver에 복사

* 두 번째 방법 :mod_symbol_import/Makefile의 KBUILD_EXTRA_SYMBOLS 변수에 mod_symbol_export/Module.symvers 절대 경로 추가





출처 : 인지소프트웨어 기술포럼 ( 전유진 강사님 수업자료)

'임베디드 > 디바이스 드라이버' 카테고리의 다른 글

Misc 디바이스 드라이버1  (0) 2017.12.26
디바이스 드라이버 구조  (0) 2017.12.26
SYSFS  (1) 2017.12.26
GPIO 제어  (0) 2017.12.26
PROCFS  (0) 2017.12.22

+ Recent posts