0

1 つのドライバーで static const int 変数を宣言し、その変数シンボルをエクスポートしました。別のドライバーで、その変数を変更しています。他のドライバーは変更された値を出力しますが、元のドライバーは元の値を保持します。両方のドライバーから見た変数の仮想アドレスと物理アドレスの両方が同じ場合、どうしてこれが可能になるのでしょうか。カーネルのバグですか?

[root@localhost bug]# uname -a
Linux localhost.localdomain 3.5.3 #3 SMP Mon Sep 3 21:52:12 IST 2012
i686 i686 i386 GNU/Linux

[root@localhost バグ]# cat driver.c

#include <linux/module.h>

static const int value = 123;

int init_module()
{
        printk("Base driver (init): value                     = %d\n", value);
        printk("Base driver (init): virtual address of value  = %p\n", (void *)&value);
        printk("Base driver (init): physical address of value = %p\n", (void
*)__pa(&value));
        return 0;
}

void cleanup_module()
{
        printk("Base driver (exit): value                     = %d\n", value);
        printk("Base driver (exit): virtual address of value  = %p\n", (void *)&value);
        printk("Base driver (exit): physical address of value = %p\n", (void
*)__pa(&value));
}
EXPORT_SYMBOL(value);

[root@localhost バグ]# cat hacker.c

#include <linux/module.h>

extern int value;

int init_module()
{
        value = 987;
        printk("Hacker driver (init): value                     = %d\n", value);
        printk("Hacker Base driver (init): virtual address of value  = %p\n",
(void *)&value);
        printk("Hacker Base driver (init): physical address of value = %p\n",
(void *)__pa(&value));
        return 0;
}

void cleanup_module()
{
        printk("Hacker driver (exit): value                     = %d\n", value);
        printk("Hacker driver (exit): virtual address of value  = %p\n",
(void *)&value);
        printk("Hacker driver (exit): physical address of value = %p\n",
(void *)__pa(&value));
        return;
}


[root@localhost bug]# insmod driver.ko

ベース ドライバー (init): 値 = 123 ベース ドライバー (init): 値の仮想アドレス = f89d61c8 ベース ドライバー (init): 値の物理アドレス = 389d61c8

[root@localhost bug]# insmod hacker.ko

Hacker ドライバー (init): 値 = 987 Hacker Base ドライバー (init): 値の仮想アドレス = f89d61c8 Hacker Base ドライバー (init): 値の物理アドレス = 389d61c8

[root@localhost bug]# rmmod hacker.ko

ハッカー ドライバー (終了): 値 = 987 ハッカー ドライバー (終了): 値の仮想アドレス = f89d61c8 ハッカー ドライバー (終了): 値の物理アドレス = 389d61c8

[root@localhost bug]# rmmod driver.ko

ベース ドライバー (終了): 値 = 123 ベース ドライバー (終了): 値の仮想アドレス = f89d61c8 ベース ドライバー (終了): 値の物理アドレス = 389d61c8

[root@localhost bug]# cat /proc/kallsyms | grep value

f89f91c8 R 値 [ドライバー] f89f9088 r __ksymtab_value [ドライバー] f89f91cc r __kstrtab_value [ドライバー]

興味深いことに、driver.c で変数の宣言を「static const volatile int」として「volatile」に変更すると、rmmod 中に driver.ko が変更された値「987」を出力し、元の値「123」が失われます。この宣言と以前の宣言の違いは何ですか?

4

1 に答える 1

5

それはカーネルとは何の関係もありません。これが基本的なCの動作です。変数constを宣言すると、コンパイラーは、同じコンパイル単位でアクセスされる場所であればどこにでも、割り当てた値を自由にインライン化できます。const変数へのポインターを取得すると、コンパイラーは、読み取り専用であると想定して、データセクションに変数のコピーも追加するように強制されます。

結果のカーネルモジュールの1つを実行objdump -dし、init_moduleを見ると、に渡されるパラメーターで、printk実際には変数にアクセスしておらず、値のインラインコピーを使用していることがわかります。

于 2012-09-04T12:29:32.473 に答える