한 모듈 은 다른 모듈 에서 내 보 낸 함 수 를 참조 합 니 다.
모듈 에서 다른 모듈 의 내 보 내기 함 수 를 참조 하 는 커 널 모듈 을 만 듭 니 다.플러스 내 보 내기 함 수 를 제공 하 는 module 작성플러스 모듈
(1) 소스 프로그램
#include
#include
#include
MODULE_LICENSE("GPL");
static int init(void)
{
printk("<0>""
plus_init success!
");
return 0;
}
static int exit(void)
{
printk("<0>""
plus_exit success!
");
return0;
}
int plus(int a, int b)
{
return(a+b);
}
EXPORT_SYMBOL(plus);
module_init(init);
module_exit(exit);
(2) Makefile 파일
ifneq ($(KERNELRELEASE),)
obj-m :=module_plus.o
else
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
Makefile 이 작성 한 구체 적 인 형식 은 나중에 분석 ~ ~ ~ ~ (3) 컴 파일, 로드, 출력 make sudoinsmod module plus. ko dmesg 를 보면 터미널 에 'plus initsuccess!'lsmod 는 모듈 로드 에 성 공 했 음 을 보 여 줍 니 다. 모듈 Size Used by module plus 12630 cat / proc / kallsyms 는 커 널 기호 표를 보면 모듈 내 보 낸 함수 00000000000000 T plus [module plus] 를 볼 수 있 습 니 다.모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈 모듈
module plus. mod. c 파일, 즉 앞에서 말 한 모듈 컴 파일 도구 체인 으로 생 성 된 것 입 니 다. 그 재 미 있 는 성명 을 보 겠 습 니 다.
struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = KBUILD_MODNAME,
.init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module,
#endif
.arch = MODULE_ARCH_INIT,
};
이 밖 에 모듈 의 버 전 정보 와 의존 관 계 를 제공 합 니 다. Module. symvers 파일 은 모듈 내 보 내기 함수 정 보 를 제공 합 니 다. 함수 주소, 함수 명, 소재 모듈 디 렉 터 리 0x668f06c 7 plus / home / l / ll / otn 프로젝트 / 프로젝트 테스트 코드 / 커 널 모듈 인 스 턴 스 / 모듈 기호 내 보 내기 인 스 턴 스 / symbol / module plus EXPORT SYMBOL 은 module test 모듈 을 작성 하여 plus 함 수 를 참조 합 니 다.일반 프로 그래 밍 코드 에 따 르 면 다음 과 같다.
(1) 소스 프로그램
#include
#include
#include
MODULE_LICENSE("GPL");
extern int plus(int,int);
static int hello_init()
{
printk(KERN_ALERT"Hello world
");
inti ;
int c = 0;
c = plus(1,2);
printk(KERN_ALERT"c = %d
",c);
return0;
}
static int hello_exit()
{
printk(KERN_ALERT"Goodbye world
");
return0;
}
module_init(hello_init);
module_exit(hello_exit);
(2) make 를 컴 파일 하면 "plus" 함수 가 정의 되 지 않 았 다 는 경 고 를 볼 수 있 습 니 다. WARNING: "plus" [/ home / l / ll / otn 프로젝트 / 프로젝트 테스트 코드 / 커 널 모듈 인 스 턴 스 / 모듈 기호 내 보 내기 인 스 턴 스 / hello / hello. ko] undefined! (3) sudoinsmod hello. ko inmod: error inserting 'hello. ko': - 1 Invalid parameters 는 사용 할 수 없 는 인자 가 있다 고 합 니 다. why? 출력 정보 dmesg 보기[2052.726996] hello: no symbol version for plus [2052.727001] hello: Unknown symbol plus (err - 22) 는 원래 "plus" 를 찾 지 못 했 습 니 다.기호, 이상 한 ing, 분명히 내 보 냈 는데, why?.......................................................................이상 한 0000000000000, 즉 커 널 기호 표 에서 이 함수 의 주 소 는 0, 즉 알 수 없 는 것 입 니 다. 어쩐지 모듈 을 불 러 올 때 해당 하 는 함수 코드 를 찾 지 못 했 습 니 다. So? How? Answer 1: module plus 모듈 이 Mododule. symvers 기호 보 기 를 생 성 하지 않 았 다 고 생각 하 십 니까? 그러면 이 파일 로 현재 hello 모듈 디 렉 터 리 에서 생 성 된 Mododule. symvers 파일 컴 파일, succe 를 대체 합 니 다.ss 로 딩, success dmesg, [2278.175896] c = 3 좋 습 니 다. 그 는 성 공 했 습 니 다. butwhy? 위대 한 뇌 를 발휘 하 세 요 ~ ~ ~ ~ ~ 앞의 모듈 로 딩 부분 을 돌 이 켜 보면 '해결 을 위 한 인용' 을 발견 할 수 있 습 니 다.기호 시 처리 함수 Answer 2: 커 널 기호 표 내 보 내기 함수 주 소 는 0 이 고 함수 가 내 보 냈 으 니 불 러 온 Module plus 모듈 에 있 는 plus 함수 의 주 소 를 찾 습 니 다.
커 널 프로 그래 밍 에서 내 보 내기 기 호 를 찾 는 함수 에 대해 구체 적 인 함수 설명 은 내 보 내기 기호 장 을 보십시오.
/*inclede/module.h*/
/*Find a symbol and return it, along with, (optional) crc and(optional) module which owns it */
const struct kernel_symbol *find_symbol(const char *name,struct module **owner,const unsigned long **crc,bool gplok,bool warn)
{
struct find_symbol_arg fsa;
fsa.name= name;
fsa.gplok= gplok;
fsa.warn= warn;
if(each_symbol(find_symbol_in_section, &fsa)) {
if(owner)
*owner= fsa.owner;
if(crc)
*crc= fsa.crc;
return fsa.sym;
}
DEBUGP("Failedto find symbol %s
", name);
return NULL;
}
EXPORT_SYMBOL(find_symbol);
//
void*__symbol_get(const char *symbol)
{
struct module *owner;
const struct kernel_symbol *sym;
preempt_disable();
sym= find_symbol(symbol, &owner, NULL, true, true);
if(sym && strong_try_module_get(owner))
sym= NULL;
preempt_enable();
return sym ? (void *)sym->value : NULL;
}
EXPORT_SYMBOL(__symbol_get);
위 프로그램 코드 를 다음 과 같이 수정 합 니 다. 저 희 는 symbol get 으로 함수 지침 을 가 져 옵 니 다.
typedef int (*plus)(int a, int b);
//extern int plus(int,int);
static int hello_init()
{
printk(KERN_ALERT"Hello world
");
plus p = NULL;
inti ;
p= (plus)__symbol_get("plus") ;
int c = 0;
//c= plus(1,2);
c = p(1,2);
printk(KERN_ALERT"c = %d
",c);
return 0;
}
make, insmod, dmesg 는 아무런 문제 도 없 이 문 제 를 해결 할 수 있 습 니 다. 이 방법 은 가능 할 것 같 습 니 다. [14534.773267] plus init success! [14681.389583] Hello world [14681.389592]c = 3 요약 하 자 면 모듈 을 불 러 올 때 인 용 된 기 호 를 처리 할 때 의존 관계 에 따라 이 기 호 를 검색 하여 인 용 된 함수 의 주 소 를 얻 을 수 있 습 니 다. 처리 하지 않 을 때 hello 모듈 을 불 러 올 때 plus 함 수 를 찾 을 수 없고 모듈 간 의존 관 계 를 만 들 수 없습니다. hello. mod. c 파일 에서
static const char module depends [] used attribute (section ("modinfo") = "depends ="; answer 1: 모듈 을 불 러 올 때 Module. symvers 파일 에 따라 내 보 낼 인용 을 사용 할 줄 알 고 모듈 module plus static const char module depends [] used attribute (section ("modinfo") = "depends = mosule plus"; answer 2: 모듈 을 불 러 올 때 커 널 내 보 내기 모듈 에 따라 "인용 해결" 을 처리 합 니 다.기호의 원칙, 여기저기 기호 표를 찾 아서 위 치 를 바 꾸 고 기호 주 소 를 찾 습 니 다 ~ ~ find symbol 은 대략 이 렇 습 니 다. 오차 가 있 을 수 있 지만 이해 에 영향 을 주지 않 습 니 다. 그러나 이 때 모듈 module plusrmodule plus 를 마 운 트 해제 하면 ERROR: Module module plus is inuse 를 알려 줍 니 다. 이 모듈 을 참조 하 는 모듈 을 마 운 트 해제 하 였 습 니 다. 왜 마 운 트 를 해제 하지 못 합 니까?모듈 은 모듈 플러스 모듈 의 상 태 를 읽 고 왜 그런 지 보 세 요.
(3) 테스트 모듈 을 작성 하여 다른 모듈 의 상 태 를 읽 습 니 다.
#include
#include
#include
#include
#include
static int __init mymod_init(void)
{
struct module *mod;
struct module_use *use;
int cpu;
//
printk(KERN_ALERT"[insmod mymod] name:%s, state:%d
",THIS_MODULE->name,THIS_MODULE->state);
// , target
list_for_each_entry(mod,THIS_MODULE->list.prev,list)
{
if(strcmp(mod->name,"module_plus")==0){
//1. 、 、
printk(KERN_ALERT"name:%s,state:%d, refcnt:%lu ",mod->name,mod->state,module_refcount(mod));
//1. module_plus ( mod->source_list)
if(!list_empty(&mod->source_list)){
list_for_each_entry(use,&mod->source_list,source_list)
printk(KERN_ALERT"%s\t",use->source->name);
}else
printk(KERN_ALERT"used by NULL
");
/*
//2. 0
for_each_possible_cpu(cpu){
per_cpu_ptr(mod->refptr, cpu)->decs = 0;
per_cpu_ptr(mod->refptr,cpu)->incs = 0;
}
//2. module_plus 、 、
printk(KERN_ALERT"name:%s,state:%d, refcnt:%lu
",mod->name,mod->state,module_refcount(mod));
*/
}
}
return 0;
}
static int __exit mymod_exit(void)
{
printk(KERN_ALERT"[rmmodmymod] name:%s state:%d
",THIS_MODULE->name,THIS_MODULE->state);
return0;
}
module_init(mymod_init);
module_exit(mymod_exit);
MODULE_AUTHOR("lilei");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Whymodule can not be removed");
코드 를 먼저 나 눠 보도 록 하 겠 습 니 다.
/*linux/module.h*/
/* */
208 enum module_state {
209 MODULE_STATE_LIVE, // 0
210 MODULE_STATE_COMING, // 1
211 MODULE_STATE_GOING, // 2
212 MODULE_STATE_UNFORMED, // 3
213};
/* */
224 struct module_ref {
225 unsigned long incs;
226 unsigned long decs;
227} __attribute((aligned(2 * sizeof(unsigned long))));
228
/*kernel/module.c*/
/* */
774 unsigned long module_refcount(struct module *mod)
775{
776 unsigned long incs = 0, decs = 0;
777 int cpu;
778
779 for_each_possible_cpu(cpu)
780 decs += per_cpu_ptr(mod->refptr, cpu)->decs;
794 smp_rmb();
795 for_each_possible_cpu(cpu)
796 incs += per_cpu_ptr(mod->refptr, cpu)->incs;
797 return incs - decs;
798}
현재 코드 1 컴 파일, 로드 모듈, dmesg [8276.079311] [insmod my mod] name: a, state: 1 [8276.079317] name: module plus, state: 0, refcnt: 1 [8276.079318]used by NULL 여기 stat: 1 은 mod - > state = MODULE STATE COMING 을 나 타 냅 니 다. 이 모듈 이 mod - > init 함 수 를 실행 하고 있 음 을 나 타 냅 니 다. mod - > state = MODULE STATE LIVING 까지 실행 되 지 않 았 음 을 나 타 냅 니 다. module plusde 의 인용 수 는 1 입 니 다. 이 모듈 의 이 값 을 0 으로 바 꾸 면 되 는 것 아 닙 니까? 주석 을 지우 고 코드 2 를 추가 하 는 오래된 과정 입 니 다.[8276.079311] [insmod my mod] name: a, state: 1 [8276.079317] name: module plus, state: 0, refcnt: 1 [8276.079318] used by NULL [8276.079321] name: module plus, state: 0, refcnt: 0 [8307.155957] [8307.155957] plus exit success! [8358.543440] [rmmod my mod] name: a state: 2 모듈 은 성공 적 으로 마 운 트 해제 되 었 는데 왜?
이 때 module plus 는 다른 모듈 에 의존 하 지 는 않 았 지만 refcnt = 1. why? hello 모듈 에 추 가 된 코드 에 bug 가 있다 는 것 을 쉽게 생각 할 수 있 습 니 다. 어 딘 가 에 모듈 수 를 1 로 더 한 것 같 습 니 다. module plus 를 작성 할 때 symbol get 으로 기 호 를 찾 습 니 다.
1886 void *__symbol_get(const char *symbol)
1887{
1888 struct module *owner;
1889 const struct kernel_symbol *sym;
1890
1891 preempt_disable();
1892 sym = find_symbol(symbol, &owner, NULL, true, true);
1893 if (sym && strong_try_module_get(owner))
1894 sym = NULL;
1895 preempt_enable();
1896
1897 return sym ? (void *)sym->value : NULL;
1898}
/* find_symbol , strong_try_module_get*/
190 static inline int strong_try_module_get(struct module *mod)
191{
192 BUG_ON(mod && mod->state ==MODULE_STATE_UNFORMED);
193 if (mod && mod->state == MODULE_STATE_COMING)
194 return -EBUSY;
195 if (try_module_get(mod))
196 return 0;
197 else
198 return -ENOENT;
199}
/* try_module_get*/
951 bool try_module_get(struct module *module)
952{
953 bool ret = true;
954
955 if (module) {
956 preempt_disable();
957
958 if (likely(module_is_live(module))) {
959 __this_cpu_inc(module->refptr->incs);
960 trace_module_get(module, _RET_IP_);
961 } else
962 ret = false;
963
964 preempt_enable();
965 }
966 return ret;
967}
놀 라 운 발견 역시 this cpu inc (module - > refptr - > incs); 모듈 의 인용 계수 에 1 을 더 했 습 니 다. 예상 한 대로 (니 마 의 것 이 나 오지 않 고 오래 찾 았 더 니 생각 났 습 니 다 ~)이것 이 바로 refcnt = 1 입 니 다. 몬스터 는 모듈 을 마 운 트 해제 할 수 밖 에 없 기 때문에 커 널 코드 도 마음대로 인용 할 수 없습니다. 특히 그의 세부 사항 을 모 를 때. 이 제 는 이 유 를 알 게 되 었 습 니 다. 함수 find symbol 을 바 꿔 보 겠 습 니 다. 모듈 의 이 변 량 값 을 직접 변경 하 는 것 은 규범 적 이지 않 기 때 문 입 니 다.
static int hello_init()
{
printk(KERN_ALERT"Hello world
");
plus p = NULL;
const struct kernel_symbol *sym;;
int c = 0;
sym = find_symbol("plus",THIS_MODULE, NULL, true, true);
if(sym) {
p= (plus*)sym->value;
c= p(1,2);
}else
sym= NULL;
p= NULL;
printk(KERN_ALERT"c = %d
",c);
return 0;
}
컴 파일, 로드, dmesg [14534.773267] plus init success! [14681.389583] Hello world [14681.389592] c = 3 ok! noproblem ~ ~ ~ 정상적으로 마 운 트 해제 되 었 습 니 다. 규범 에 맞 는 지 는 저도 잘 모 르 겠 지만 이것 도 방법 이 라 고 할 수 있 습 니 다. 2.6 커 널 의 해결 ~ 참고 하 세 요.http://blog.csdn.net/zhangskd/article/details/7945140
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
LCS+LIS텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.