😺
カーネルモジュール作成
カーネルモジュール作成
mymodule.c
#include <linux/module.h>
static int __init mymodule_init(void)
{
printk(KERN_INFO "hello module\n");
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");
Makefile
Makefile
obj-m := mymodule.o
KDIR := /lib/modules/$(shell uname -r)/build
VERBOSE = 0
all:
$(MAKE) -C $(KDIR) M=$(PWD) KBUILD_VERBOSE=$(VERBOSE) CONFIG_DEBUG_INFO=y modules
clean:
m -f *.o *.ko *.mod.c Module.symvers modules.order
make
sudo insmod ./mymodule.ko -f モジュールインストール
dmesgでhello moduleを確認
modinfo mymodule.ko モジュール調査
rmmod mymodule -f モジュール削除
journalctl -f
モジュール情報
$ modinfo mymodule.ko
filename: /home/shiroyama/Documents/mymodule/mymodule.ko
license: GPL v2
author: shiroyama
depends:
retpoline: Y
name: mymodule
vermagic: 5.10.0-19-amd64 SMP mod_unload modversions
カーネル変数を表示してみる。
*System.mapに登録されていて、extern宣言しているヘッダーファイルをインクルードすれば、モジュール内で表示することができる。
mymodule.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/current.h>
#include <linux/sched.h>
#include <generated/utsrelease.h>
#include <linux/version.h>
#include <linux/uts.h>
#include <linux/utsname.h>
#include <linux/sysctl.h>
#include <linux/cpumask.h>
#include <asm/processor.h> //struct cpuinfo_x86
#include <linux/slab.h> //kmalloc
#include <asm-generic/io.h> //virt_to_phys
static void *virtual_addr;
static phys_addr_t physical_addr;
int size = 1024; /* allocate 1024 bytes */
static int __init mymodule_init(void)
{
struct uts_namespace *uts_ns;
typeof(current_task) task;
u64 pfo_val__;
struct cpuinfo_x86 *cpu0 = &cpu_data(0);
struct cpuinfo_x86 *cpu1 = &cpu_data(1);
//struct cpuinfo_x86 *cpu2 = &cpu_data(3);
int i = 0;
printk(KERN_INFO "hello module\n");
/* print information and return an error */
printk("Machine Name: %s\n",init_uts_ns.name.machine);
printk("System Name: %s\n",init_uts_ns.name.sysname);
printk("Release: %s\n",init_uts_ns.name.release);
printk("Version: %s\n",init_uts_ns.name.version);
uts_ns = get_current()->nsproxy->uts_ns;
printk(KERN_INFO "uts_ns sysname %s\n", uts_ns->name.sysname);
printk(KERN_INFO "uts_ns nodename %s\n", uts_ns->name.nodename);
printk(KERN_INFO "uts_ns release %s\n", uts_ns->name.release);
printk(KERN_INFO "uts_ns version %s\n", uts_ns->name.version);
printk(KERN_INFO "uts_ns machine %s\n", uts_ns->name.machine);
printk(KERN_INFO "uts_ns domainname %s\n", uts_ns->name.domainname);
printk(KERN_INFO "uts_ns %p\n", uts_ns);
//cpu variable
printk(KERN_INFO "nr_cpu_ids %d\n", nr_cpu_ids);
printk(KERN_INFO "nr_node_ids %d\n", nr_node_ids);
//cpumask macro /include/linux/cpumask.h
printk(KERN_INFO "num_online_cpus %d\n", num_online_cpus());
printk(KERN_INFO "num_possible_cpus %d\n", num_possible_cpus());
printk(KERN_INFO "num_present_cpus %d\n", num_present_cpus());
printk(KERN_INFO "num_active_cpus %d\n", num_active_cpus());
//cpuinfo_x86 /arch/x86/include/asm/processor.h
printk(KERN_INFO "x86 %hhu\n", cpu0->x86);
printk(KERN_INFO "x86_vendor %hhu\n", cpu0->x86_vendor);
printk(KERN_INFO "x86_model %hhu\n", cpu0->x86_model);
printk(KERN_INFO "x86_tlbsize %hhu\n", cpu0->x86_tlbsize);
printk(KERN_INFO "x86_max_cores %u\n", cpu0->x86_max_cores);
printk(KERN_INFO "apicid %u\n", cpu0->apicid);
printk(KERN_INFO "booted_cores %u\n", cpu0->booted_cores);
printk(KERN_INFO "phys_proc_id %u\n", cpu0->phys_proc_id);
printk(KERN_INFO "logical_proc_id %u\n", cpu0->logical_proc_id);
printk(KERN_INFO "cpu_core_id %u\n", cpu0->cpu_core_id);
printk(KERN_INFO "cpu_index %u\n", cpu0->cpu_index);
printk(KERN_INFO "microcode %u\n", cpu0->microcode);
//currentマクロ展開
asm("movq %%gs:%P[var], %[val]" : [val] "=r" (pfo_val__) : [var] "p" (&(current_task)));
task = (typeof(current_task))(unsigned long) pfo_val__;
printk(KERN_INFO "release %s\n", task->nsproxy->uts_ns->name.release);
//task_struct
printk(KERN_INFO "__state %u\n", task->__state);
printk(KERN_INFO "flags %u\n", task->flags);
printk(KERN_INFO "ptrace %u\n", task->ptrace);
printk(KERN_INFO "on_cpu %d\n", task->on_cpu);
printk(KERN_INFO "recent_used_cpu %d\n", task->recent_used_cpu);
printk(KERN_INFO "wake_cpu %d\n", task->wake_cpu);
printk(KERN_INFO "on_rq %d\n", task->on_rq);
printk(KERN_INFO "prio %d\n", task->prio);
printk(KERN_INFO "pid %d\n", task->pid);
printk(KERN_INFO "tgid %d\n", task->tgid);
printk(KERN_INFO "x86_model %hhu\n", cpu1->x86_model);
//printk(KERN_INFO "x86_model %hhu\n", cpu2->x86_model);
virtual_addr = kmalloc(size,GFP_ATOMIC);
if(!virtual_addr) {
/* handle error */
pr_err("memory allocation failed\n");
return -ENOMEM;
} else {
pr_info("Memory allocated successfully Virtual address:%p\n", virtual_addr);
physical_addr = virt_to_phys(virtual_addr);
pr_info("Physical address:%llx\n", physical_addr);
pr_info("Virtual address:%p\n", phys_to_virt(physical_addr));
}
kfree(virtual_addr);
//get_cpu このモジュールを実行しているCPU番号 実行する度に異なる
for_each_online_cpu(i) {
printk(KERN_INFO "for_each_online_cpu: i= %d id= %d\n", i, get_cpu());
}
i = 0;
for_each_cpu(i, cpu_online_mask) {
printk(KERN_INFO "cpu_online_mask: i= %d id= %d\n", i, get_cpu());
}
i = 0;
for_each_cpu(i, cpu_possible_mask) {
printk(KERN_INFO "cpu_possible_mask: i= %d id= %d\n", i, get_cpu());
}
i = 0;
for_each_cpu(i, cpu_dying_mask) {
printk(KERN_INFO "cpu_possible_mask: i= %d id= %d\n", i, get_cpu());
}
printk(KERN_INFO "sizeof(cpu_online_mask) = %lu\n", sizeof(cpu_online_mask));
printk(KERN_INFO "sizeof(cpu_dying_mask) = %lu\n", sizeof(cpu_dying_mask));
//dummy for_each_cpu
printk(KERN_INFO "nr_cpu_ids = %d\n", nr_cpu_ids);
for(i = 0; i < nr_cpu_ids; i = cpumask_next(i, cpu_online_mask)) {
printk(KERN_INFO "dummy for_each_cpu = %d %lu\n", i, cpu_online_mask->bits[i]);
}
printk(KERN_INFO "cpu_mask_check = %u\n", cpumask_last(cpu_online_mask));
//cpu_dying_mask
//cpu_active_mask
//cpu_possible_mask
//get_cpu()
//get_online_cpus
//put_online_cpus
//cpu_mask_check
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");
Discussion