🐷

PER_CPU変数

2022/12/14に公開

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);最初の数値になる?

https://wiki.bit-hive.com/north/pg/CPU変数

https://stackoverflow.com/questions/11635234/how-to-get-the-current-task-for-a-given-cpu-in-smp-linux

http://www.makelinux.net/ldd3/chp-8-sect-5.shtml

https://stackoverflow.com/questions/56097946/get-cpu-var-put-cpu-var-not-updating-the-per-cpu-variable

http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch11lev1sec11.html

https://stackoverflow.com/questions/16978959/how-are-percpu-pointers-implemented-in-the-linux-kernel

https://akachochin.hatenadiary.org/entry/20101005/1286289176

https://mmi.hatenablog.com/entry/2017/03/30/000627

Discussion