"Segmentation fault" 当 `rmmod` 或 `modprobe -r`
"Segmentation fault" when `rmmod` or `modprobe -r`
尝试使用 LDD3 中最简单的内核模块,无需对带有 BusyBox v1.23.0 的 Beagle Bone 板的自定义构建内核 v4.1.0-rc6 进行任何修改。该模块的代码如下:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile 是:
ARCH := arm
CROSS_COMPILE := arm-cortex_a8-linux-gnueabi-
obj-m := hello.o
all:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) modules
clean:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) clean
模块正在rootfs上正常编译安装。它还正在加载:
$ insmod hello.ko
[ 30.692404] Hello, world
但是在尝试删除它时,我得到:
$ rmmod hello.ko
Segmentation fault
$modprobe -r hello.ko
Segmentation fault
$ lsmod
hello 813 0 - Live 0xbf000000 (O)
编译内核时启用了模块卸载(常规和强制)支持。
导致此问题的可能原因是什么?调查方法是什么?
更新:
正如我尝试过的评论中所建议的那样,包括 linux/kernel.h
,定义了 MODULE
、LINUX
和 __KERNEL__
符号。为函数添加了 __init
和 __exit
前缀。删除了 static
修饰符。删除了 printk
行。结果一样。 dmesg
仅显示初始问候语。加载和卸载内核模块,如 gpio_keys
或 crypto/ccm
是 工作,令人惊讶。所以唯一值得怀疑的是模块的编译方式..
更新 2
将内核更新到最新的快照没有帮助。使用不同的优化设置编译模块没有帮助。下一步,我想,我将修改 BusyBox 的 rmmod 以指示问题位置..
看看这些教程:
http://www.tldp.org/HOWTO/Module-HOWTO/x839.html
http://www.tldp.org/LDP/lkmpg/2.4/html/x281.htm
尝试添加:
#define MODULE
#define LINUX
#define __KERNEL__
#include <linux/kernel.h> /* Needed for KERN_ALERT */
我已经设法解决了这个问题。使用 strace
我发现当 read
ing BusyBox
特定的 modules.dep.bb
文件时,段错误发生在某处。此文件在使用 "Simplified modutils" 选项 (CONFIG_MODPROBE_SMALL
) 编译时由 BusyBox
使用。通过禁用该选项,选择要安装的实用程序并重建 BusybBox,我已经完成了模块卸载工作。我相信问题的根源在于测试模块被编译并存储在 /lib/..../modules
目录之外,因此 busybox
与简化的 modutils
只是变得混乱。
尝试使用 LDD3 中最简单的内核模块,无需对带有 BusyBox v1.23.0 的 Beagle Bone 板的自定义构建内核 v4.1.0-rc6 进行任何修改。该模块的代码如下:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile 是:
ARCH := arm
CROSS_COMPILE := arm-cortex_a8-linux-gnueabi-
obj-m := hello.o
all:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) modules
clean:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) clean
模块正在rootfs上正常编译安装。它还正在加载:
$ insmod hello.ko
[ 30.692404] Hello, world
但是在尝试删除它时,我得到:
$ rmmod hello.ko
Segmentation fault
$modprobe -r hello.ko
Segmentation fault
$ lsmod
hello 813 0 - Live 0xbf000000 (O)
编译内核时启用了模块卸载(常规和强制)支持。
导致此问题的可能原因是什么?调查方法是什么?
更新:
正如我尝试过的评论中所建议的那样,包括 linux/kernel.h
,定义了 MODULE
、LINUX
和 __KERNEL__
符号。为函数添加了 __init
和 __exit
前缀。删除了 static
修饰符。删除了 printk
行。结果一样。 dmesg
仅显示初始问候语。加载和卸载内核模块,如 gpio_keys
或 crypto/ccm
是 工作,令人惊讶。所以唯一值得怀疑的是模块的编译方式..
更新 2
将内核更新到最新的快照没有帮助。使用不同的优化设置编译模块没有帮助。下一步,我想,我将修改 BusyBox 的 rmmod 以指示问题位置..
看看这些教程:
http://www.tldp.org/HOWTO/Module-HOWTO/x839.html http://www.tldp.org/LDP/lkmpg/2.4/html/x281.htm
尝试添加:
#define MODULE
#define LINUX
#define __KERNEL__
#include <linux/kernel.h> /* Needed for KERN_ALERT */
我已经设法解决了这个问题。使用 strace
我发现当 read
ing BusyBox
特定的 modules.dep.bb
文件时,段错误发生在某处。此文件在使用 "Simplified modutils" 选项 (CONFIG_MODPROBE_SMALL
) 编译时由 BusyBox
使用。通过禁用该选项,选择要安装的实用程序并重建 BusybBox,我已经完成了模块卸载工作。我相信问题的根源在于测试模块被编译并存储在 /lib/..../modules
目录之外,因此 busybox
与简化的 modutils
只是变得混乱。