😺

カーネルモジュール作成

2022/10/18に公開

カーネルモジュール作成

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