9

このモジュールをロードすると:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void) {
  printk("<1> Hello world!\n");
  return 0;
}

static void hello_exit(void) {
  printk("<1> Bye, cruel world\n");
}


module_init(hello_init);
module_exit(hello_exit);

( http://www.freesoftwaremagazine.com/articles/drivers_linux?page=0,2より)

モジュールは2.6.39-02063904-generic で ( Ubuntu PPA[permanent]から) としてマークされ、lsmodアンロードできません。しかし、デフォルトの 2.6.38 カーネルでは問題なく動作します。(どちらも Ubuntu 11.04 x86 で)。

2.6.39 で何が変更されましたか? コードで何を変更する必要がありますか?

この問題に遭遇したとき、私はより複雑な問題を切り分けようとしていました。

編集:

回答からの提案に従って、コードを編集して(hello3.c)を追加__initしました。__exit

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("Dual BSD/GPL");

static int __init hello_init(void) {
  printk("<1> Hello world!\n");
  return 0;
}

static void __exit hello_exit(void) {
  printk("<1> Bye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

ビルド出力:

make -C /lib/modules/2.6.39-02063904-generic/build M=/home/douglas/kernelmod modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.39-02063904-generic'
Building with KERNELRELEASE = 2.6.39-02063904-generic
  CC [M]  /home/douglas/kernelmod/hello3.o
  Building modules, stage 2.
Building with KERNELRELEASE = 2.6.39-02063904-generic
  MODPOST 8 modules
  CC      /home/douglas/kernelmod/hello3.mod.o
  LD [M]  /home/douglas/kernelmod/hello3.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.39-02063904-generic'

EDIT2:

hello3.mod.c:

#include <linux/module.h>
#include <linux/vermagic.h>
#include <linux/compiler.h>

MODULE_INFO(vermagic, VERMAGIC_STRING);

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,
};

static const struct modversion_info ____versions[]
__used
__attribute__((section("__versions"))) = {
    { 0xbe4b3e92, "module_layout" },
    { 0xb4390f9a, "mcount" },
    { 0x5e3b3ab4, "printk" },
};

static const char __module_depends[]
__used
__attribute__((section(".modinfo"))) =
"depends=";


MODULE_INFO(srcversion, "D2A869459874C22AB265981");

また

# grep CONFIG_MODULE_UNLOAD /boot/config-2.6.39-02063904-generic 
CONFIG_MODULE_UNLOAD=y

EDIT3:

さらに興味深いことに、私が自分でコンパイルしたバニラカーネルでは発生しません-モジュールを正常にロードおよびアンロードします。

EDIT4:

Oneiric ベータ 2 ビルドを VM にインストールしましたが、その 3.0.0-11 カーネルにも問題はありません。そのため、Ubuntu Vanilla PPA カーネルに限定されているようです。それを解決するのはあまり楽しいことではありません。

4

4 に答える 4

7

だから、Canonicalと相談した後、私は問題が何であるかを知っています:

Ubuntu のメインライン ビルドは Hardy ツール チェーンを使用してビルドされており、11.04 および 11.10 ツール チェーンは、ツリー外のカーネル モジュールのビルドとは互換性がありません。

于 2011-09-27T19:27:52.917 に答える
6

「structmodule」レイアウトは、使用されているgccバージョンに依存するgcc-goto.shスクリプト結果に依存するCC_HAVE_ASM_GOTO定義に依存するHAVE_JUMP_LABEL定義に依存します。不一致がある場合、モジュール出口コールバック(デストラクタ)はNULLの値を取得し、その結果、モジュールは[永続的]としてマークされます。

于 2012-09-20T17:22:00.913 に答える
1

カーネル ソースからわかる限り、init 関数はあるが exit 関数がないモジュールは永続的とマークされます。

この場合、完全にはわかりませんが、init 関数と exit 関数をそれぞれ と でマークすることをお勧めし__initます__exit。(また、modpost によって発せられる警告にも注意してください)

于 2011-09-20T09:42:26.877 に答える
0

この問題は、古い gcc コンパイラが間違ったモジュール バイナリ形式を生成し、モジュールの終了関数がカーネルから適切なアンロード情報を取得できないことが原因です。

gcc のバージョンが 4.4 かどうかを確認できます。その場合は、4.6 を使用するように変更すると問題が修正されます。

gcc --version

4.4 バージョンの場合は、/usr/bin/gcc のシンボル リンクを削除し、/usr/bin/gcc-4.6 に再リンクします。モジュールの削除は、再コンパイル後に機能するはずです。

于 2014-06-26T07:20:49.067 に答える