모듈 insmod와 rmmod 오류 해결 방안
5824 단어 linux 커널 모듈
문제 설명
요 며칠 동안 Linux 핵을 공부할 때 사람을 미치게 하는 문제를 만났다. 문제는 다음과 같다. 핵 모듈을 작성할 때 코드에 오류가 발생했지만 컴파일러가 검사하지 않았다. 예를 들어 일부 메모리의 문제, 빈 바늘에 접근했다. 나는 실수로 NULL 바늘에 값을 부여하는 비교를 해서 insmod**에 부딪혔다.ko에서 오류가 발생하여 처음으로 KILL을 직접 알립니다.이유를 알 수 없을 때 두 번째 insmod가 막히니까 거기서 렉이 걸렸다고 해야겠죠.
문제 분석
코드 때문에 이 문제가 발생한 것은 슬프다. lsmod를 통해 불러온 모듈을 보면 이전에 insmod의 모듈이 존재했지만 마운트할 수 없고 인용 계수가 0이 되지 않았다.다시cat/proc/modules를 통해 이 모듈의 상태는loading이지 living이 아니라는 것을 알 수 있습니다.그래서 이 모듈을 마운트 해제하려면 이 두 가지를 수정하고 상태와 인용 계수를 0으로 수정해야 합니다.
문제 해결
문제를 찾아 분석하고 나면 문제를 해결하기 시작할 수 있다.수동 insmod를 통해 불러오는 모듈은 임시이기 때문에 리셋을 통해 상술한 문제를 해결할 수 있지만 매번 리셋할 수 없습니다. 따라서 insmod라는 모듈을 다시 작성하여 그 오류 모듈의 관련 속성을 수정합니다.커널 소스를 보면 struct module 구조에 포함된 다음 구성원이 표시됩니다.
struct module {
enum module_state state; // ,
char name[MODULE_NAME_LEN]; //
struct module_ref __percpu *refptr; //
}
enum module_state {
MODULE_STATE_LIVE, /* Normal state. */
MODULE_STATE_COMING, /* Full formed, running module_init. */
MODULE_STATE_GOING, /* Going away. */
MODULE_STATE_UNFORMED, /* Still setting it up. */
};
우리는 상태와 인용 계수를 수정하면 된다.
/*print_module.c*/
#include
#include
#include
#include
MODULE_LICENSE("GPL");
/*
**
**sudo cat /pro/kallsyms | grep [^_]modules$
*/
#define MODULES 0xffffffff8ec5b470
/* */
#define DEBUG_MODULE 0
/* */
#define DEBUG 1
static char *name = "testtesttest";
/* , */
module_param(name,charp,S_IRUGO);
static int __init print_module_init(void)
{
struct list_head *module_head;
struct list_head *pos;
struct module *p;
int i= 0;
int ret;
printk(KERN_INFO "print module init
");
module_head = (struct list_head*)MODULES;
/* module*/
list_for_each(pos,module_head) {
p = list_entry(pos,struct module,list);
#if DEBUG
#if DEBUG_MODULE
/* , living, */
if(strcmp(p->name,name)==0){
p->state = MODULE_STATE_LIVE;
if((ret = try_module_get(p)) == 0) {
printk(KERN_ALERT "try_module_get error
");
}
printk(KERN_INFO "%s ret is inc
",p->name);
}
#else
/* */
if(strcmp(p->name,name) == 0) {
module_put(p);
printk(KERN_INFO "%s ref is dec
",p->name);
}
#endif
#endif
}
return 0;
}
static void __exit print_module_exit(void)
{
printk(KERN_INFO "print module exit
");
}
module_init(print_module_init);
module_exit(print_module_exit);
Makefile은 다음과 같습니다.
obj-m:= print_module2.o
KDIR:= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KDIR) M=$(shell pwd) modules
clean:
$(MAKE) -C $(KDIR) M=$(shell pwd) clean
컴파일 통과 후 insmod printmodule.ko name=xxxx를 불러옵니다. xxx는 잘못된 모듈입니다. 그 과정에서 lsmod와cat/proc/modules를 통해 모듈 관련 정보를 볼 수 있습니다