http://www.troot.co.kr/tc/2671
http://stackoverflow.com/questions/16360689/invalid-parameters-error-when-trying-to-insert-module-that-accesses-exported-s - insert module 시 Invaild parameters 오류 발생시, 모듈 컴파일시 undefined 오류 발생시 해결법
1. 특정 모듈 컴파일시 필요한것
1. 커널 소스 헤더와 의존되는 모듈이 있다면 해당 모듈의 심볼 테이블이다.
심볼 테이블의 이름은 Module.symvers 이다.
심볼 테이블은 모듈을 컴파일하면 해당 디렉토리에 생성되며 함수의 위치 정보를 가지고 있다.
2. 커널 소스 혹은 커널 헤더
sudo apt-get install linux-source 나 sudo apt-get install linux-headers-x.x.x 을 통해 받을수 있다. 대체로 위치는 /usr/src 에 존재한다.
2. 특정 모듈 컴파일시 Makefile
obj-m = {modulename}.o {modulename}-y = {file}.o ccflags-y += {추가할 헤더경로} KBUILD_EXTRA_SYMBOLS = {참조할 심볼 테이블} all: clean: |
예들 들어
1. test.ko 란 모듈을 제작하려고 하고 해당 모듈은 소스파일 /test/foo.c , /test/bar.c 로 이루어져 있다고 하자.
그리고 /test/include/foo.h , /test/include/bar.h 헤더가 존재한다고 하자. 그리고 libtest.ko 의 함수를 test.ko 에서 사용한다고 하자.
2. libtest.ko 란 모듈은 소스파일 /libtest/libtest.c 로 이루어져 있다고 하자. 헤더는 따로 없다.
그리고 /usr/src/linux-headers-3.10 에 헤더파일들이 존재한다고 하자.
* 커널 헤더는 sudo apt-get install linux-headers 명령을 통해 받을수 있다. 혹은 그냥 커널 소스 자체를 받아도 된다.
이때 test.ko 에 대한 Makefile 은 /test/ 안에 생성해야한다.
obj-m += test.o test-y := foo.o bar.o PWD = $(shell pwd) ccflags-y += -I/test/include KBUILD_EXTRA_SYMBOLS += /libtest/Module.symvers all: make -C /usr/src/linux-headers-3.10/ M=${PWD} modules clean: make -C /usr/src/linux-headers-3.10/ M=${PWD} clean |
libtest.ko 에 대한 Makefile은 /libtest/ 안에 생성한다.
obj-m += libtest.o PWD = $(shell pwd) all: make -C /usr/src/linux-headers-3.10/ M=${PWD} modules clean: make -C /usr/src/linux-headers-3.10/ M=${PWD} clean |
컴파일은 해당 디렉토리에 가서 make all 하면된다.
test.ko 는 libtest.ko의 함수를 사용하기 때문에 libtest.ko 의 심볼 테이블이 필요하다. 그러므로 libtest.ko 를 우선 컴파일 해야한다.
libtest.ko 를 컴파일하면 해당 디렉토리에 Module.symvers 심볼 테이블 파일이 생성된다.
그후 test.ko 를 컴파일하면 이상없이 컴파일 될것이다.
3. Makefile 설명
1. obj-m : 생성할 모듈 이름이다. 예를 들어 test.ko 를 생성하고 싶다면 test.o 를 인자로 주면된다.(test.ko 가 아니다.)
obj-m += test.o |
2. {module_name}-y : 해당 모듈을 구성하는 소스리스트를 적어주면된다. 주의할 것은 .o 이지 .c 가 아니다. 예를들어 test.ko 를 구성하는 소스가 foo.c, bar.c 라면
test-y := foo.o bar.o |
3. PWD = $(shell pwd) : 그냥 현재 경로이다.
4. ccflags-y : 이것은 컴파일시 gcc 에 포함할 옵션이다. 예를들어 참조하는 헤더의 위치가 /home/include 라면 이 경로는 gcc가 암시적으로 참조하지 않는다. 따라서 옵션을 주어 해당경로에서도 헤더를 찾으라고 해야한다. 헤더가 위치한 경로를 주는 옵션은 대문자 I 이다.
ccflags-y += -I/home/include |
5. KBUILD_EXTRA_SYMBOLS : 참조할 심볼 테이블 파일의 경로이다. 심볼 테이블 파일의 이름은 Module.symvers 이다. 예를 들어 참조하는 심볼 테이블의 경로가 /libtest/Module.symvers 라면
KBUILD_EXTRA_SYMBOLS += /libtest/Module.symvers |
6. all , clean : 여기의 make -C 옵션 값은 커널 헤더 최상위 경로거나 커널 소스 최상위 경로이면 된다.
셋중 하나면 된다. 중요한 것은 현재 커널 버젼 uname -r 과 동일해야한다는 것이다.
make -C /usr/src/linux-headers-$(shell uname -r)/ M=$(PWD) modules 혹은 make -C /usr/src/linux-$(shell uname -r)/ M=$(PWD) modules 혹은 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules |
기본 linux/xxxx.h 헤더는 /usr/src/linux-$(shell uname -r)/include 에서 찾는다.
4. 예시
아래와 같이 많이 쓴다.
CONFIG_TEST = m obj-$(CONFIG_TEST) += test.o test-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \ export.o caps.o snap.o PWD = $(shell pwd) BASE_DIR = $(shell dirname $(PWD)) #ccflags-y += -I/home/user/include #KBUILD_EXTRA_SYMBOLS += /home/user/lib/Module.symvers all: make -C /usr/src//linux-headers-$(shell uname -r)/ M=$(PWD) ccflags-y+=-I$(BASE_DIR)/include KBUILD_EXTRA_SYMBOLS+=$(BASE_DIR)/net/Module.symvers modules clean: make -C /usr/src/linux-headers-$(shell uname -r)/ M=$(PWD) clean |
대충 이런식으로 많이 쓴다.
ccflags-y 나 KBUILD_EXTRA_SYMBOLS 변수 같은 경우
cflags-y += -I${BASE_DIR}/include 이런식으로 쓰면 오류가 나더라.
그래서 make cflags-y += -I${BASE_DIR}/include 이런식으로 make 명령에 직접 옵션으로 붙인다.
5. 모듈 추가
추가는 쉽다.
해당 모듈이 존재하는 디렉토리에서
sudo insmod test.ko 라고 치면 된다. 여기서 중요한 점은 test.ko 가 libtest.ko 의 함수를 쓴다면 우선 libtest.ko 모듈을 로드한 후에 test.ko 를 로드해야한다.
insmod 는 해당 모듈이 존재하는 곳에서 로드하는 방법이고 modprobe를 사용하기 위해서는
/lib/modules/`uname -r`/kernel/ 밑에 적절한 디렉토리를 선택하거나 디렉토리를 생성하고 .ko 파일을 복사하면 된다.
복사한 후에는 modprobe 로 추가하기 전에 depmod -a 명령을 우선 수행해서 복사한 .ko 파일을 인식시켜야한다.
$ sudo depmod -a
$ sudo modprobe {module}.ko
아 그리고 test.ko 가 libtest.ko 의 함수를 사용할 때 즉 test.ko 가 libtest.ko 를 의존할때는 libtest.ko 를 우선 로드후에 test.ko를 로드해야한다.
6. 모듈 정보 보기
modinfo {모듈경로}
예를 들어
$ modinfo /lib/modules/3.11.8/kernel/fs/xfs/xfs.ko filename: /lib/modules/3.11.8/kernel/fs/xfs/xfs.ko |
7. 오류
만약 컴파일 중에 undefined 에러나, 모듈을 insmod 중에 Invalid parameters 에러가 발생한다면 현재 모듈이 다른 모듈의 함수를 사용했을 경우다. 이때는 사용하려는 해당 모듈이 컴파일 되기전에 함수에 대한 심볼 테이블이 필요하다.
만약 foo.ko 가 bar.ko 의 함수를 사용한다면 우선 bar.ko 를 컴파일 한다. 컴파일하면 해당 폴더에 Module.symvers 란 파일이 생성된다. 이 파일을 foo.ko 가 컴파일될 폴더에 복사한후 foo.ko를 컴파일하면 에러 없이 컴파일되고 에러 없이 insmod 될 것이다.
혹은 makefile 에 KBUILD_EXTRA_SYMBOLS += {Module.symvers} 를 추가한다.
글이 참.. 설명 능력좀 키워야하나..
'학습자료(~2017) > 리눅스' 카테고리의 다른 글
[Linux] 폴더내 모든 문서의 특정 문자열 치환, 폴더내 모든 문서의 특정 이름 변경 (1) | 2014.03.04 |
---|---|
ubuntu release upgrade 우분투 릴리즈 업그레이드 (0) | 2013.11.19 |
커널 컴파일 (0) | 2013.11.18 |
[linux] apt-get 저장소를 추가/변경 해보자 (0) | 2013.11.05 |
[linux] memory cache 초기화 (0) | 2013.10.15 |