🐷
PER_CPU変数
PER_CPU変数
#include <linux/module.h>
#include <linux/kmod.h>
//CPU毎に変数xを設定する
static DEFINE_PER_CPU(int, x) = 100;
static int __init mymodule_init(void)
{
int i = 0;
printk(KERN_INFO "\n******** PER_CPU BEFORE ********\n");
for_each_cpu(i, cpu_online_mask) {
printk(KERN_INFO "cpu %2d x= %d address = %p\n", i, per_cpu(x, i), &per_cpu(x, i));
}
printk("get_cpu() %d\n", get_cpu());//現在のcpuidを取得
this_cpu_write(x, 200);//現在のCPUのxだけ200に変更する
get_cpu_var(x)++;//インクリメントするから201になる
put_cpu_var(x);//変数更新
printk(KERN_INFO "\n******** PER_CPU AFTER ********\n");
i = 0;
for_each_cpu(i, cpu_online_mask) {
printk(KERN_INFO "cpu %2d x= %d address = %p\n", i, per_cpu(x, i), &per_cpu(x, i));
}
return 0;
}
static void __exit mymodule_exit(void)
{
printk(KERN_INFO "bye module\n");
}
module_init(mymodule_init);
module_exit(mymodule_exit);
MODULE_AUTHOR("shiroyama");
MODULE_LICENSE("GPL v2");
表示してみるとわかるが、per_cpuのアドレスはバラバラです。
currnet_taskもPER_CPU変数として宣言されている。
/arch/x86/kernel/cpu/common.c
DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned =
&init_task;
current_taskをすべて表示してみる。
//sudo insmod ./current.ko;sudo dmesg;sudo rmmod current;
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/nsproxy.h>
#include <linux/utsname.h>
DECLARE_PER_CPU(struct task_struct *, current_task);
static int __init mymodule_init(void)
{
int i;
struct task_struct *p;
printk("get_cpu() %d\n", get_cpu());//現在のcpuidを取得
for_each_cpu(i, cpu_online_mask) {
p = per_cpu(current_task, i);
printk(KERN_INFO "current %02d x= %p %s\n", i, p, p->nsproxy->uts_ns->name.release);
}
return 0;
}
static void __exit mymodule_exit(void)
{
printk(KERN_INFO "bye module\n");
}
module_init(mymodule_init);
module_exit(mymodule_exit);
MODULE_AUTHOR("shiroyama");
MODULE_LICENSE("GPL v2");
結果
get_cpu() 3
current 00 x= 00000000d26b4ff3 6.1.0-rc6
current 01 x= 0000000067b627db 6.1.0-rc6
current 02 x= 000000005ecca7f9 6.1.0-rc6
current 03 x= 0000000099f2b591 6.1.0-rc6
current 04 x= 00000000700f9eb0 6.1.0-rc6
それぞれのcurrent_taskでlinuxバージョンがちゃんと表示されている。
アドレスの方はバラバラなようだ。
☆ここで%gsレジスタを表示するとどうなる?current_taskのアドレスと比較する。
printk("%d", x);最初の数値になる?
Discussion