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」が失われます。この宣言と以前の宣言の違いは何ですか?