"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,定义了 MODULELINUX__KERNEL__ 符号。为函数添加了 __init__exit 前缀。删除了 static 修饰符。删除了 printk 行。结果一样。 dmesg 仅显示初始问候语。加载和卸载内核模块,如 gpio_keyscrypto/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 我发现当 reading BusyBox 特定的 modules.dep.bb 文件时,段错误发生在某处。此文件在使用 "Simplified modutils" 选项 (CONFIG_MODPROBE_SMALL) 编译时由 BusyBox 使用。通过禁用该选项,选择要安装的实用程序并重建 BusybBox,我已经完成了模块卸载工作。我相信问题的根源在于测试模块被编译并存储在 /lib/..../modules 目录之外,因此 busybox 与简化的 modutils 只是变得混乱。