差異處
這裏顯示兩個版本的差異處。
cpp:linux_kernel:show_physical_address [2017/10/02 00:52] tony |
cpp:linux_kernel:show_physical_address [2023/06/25 09:48] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | ====== Show Physical Memory Address of the kernel module ====== | ||
- | ===== Introduction ===== | ||
- | 我希望透過寫一個kernel module,做以下事情: | ||
- | - 宣告一個global variable。 | ||
- | - init時,初始此variable。 | ||
- | - 執行file_operations: open時,會打印出此變數的實體記憶體位置。 | ||
- | - exit時,釋放此variable。 | ||
- | ===== How to? ===== | ||
- | <code> | ||
- | # | ||
- | ## Makefile for kernel test | ||
- | # | ||
- | #PWD := $(shell pwd) | ||
- | KVERSION := $(shell uname -r) | ||
- | KERNEL_DIR = /usr/src/kernels/$(KVERSION)/ | ||
- | MODULE_NAME = hello | ||
- | obj-m := $(MODULE_NAME).o | ||
- | all: | ||
- | make -C $(KERNEL_DIR) M=$(PWD) modules | ||
- | clean: | ||
- | make -C $(KERNEL_DIR) M=$(PWD) clean | ||
- | </code> | ||
- | |||
- | <code cpp> | ||
- | #include <linux/init.h> | ||
- | #include <linux/module.h> | ||
- | #include <linux/slab.h> | ||
- | #include <linux/string.h> | ||
- | #include <asm/io.h> | ||
- | #include <linux/fs.h> | ||
- | |||
- | MODULE_LICENSE("Dual BSD/GPL"); | ||
- | |||
- | static char* hello_buf; | ||
- | |||
- | static int dump_physical_address(struct file *filp, struct vm_area_struct *vma) | ||
- | { | ||
- | unsigned long virt_addr; | ||
- | phys_addr_t phy_addr; | ||
- | printk("damn\n"); | ||
- | virt_addr = (unsigned long)hello_buf; | ||
- | printk("Hello kernel: %lx, value: %c\n", virt_addr, hello_buf[0]); | ||
- | phy_addr = virt_to_phys((void*)virt_addr); | ||
- | printk("PA: 0x%lx\n", phy_addr); | ||
- | pr_info("PA: %pa for VA: 0x%lx\n", &phy_addr, virt_addr); | ||
- | return 0; | ||
- | } | ||
- | |||
- | static struct file_operations hello_fops = { | ||
- | open: dump_physical_address, | ||
- | }; | ||
- | |||
- | static int hello_init(void) | ||
- | { | ||
- | |||
- | int ret = register_chrdev(187, "hello", &hello_fops); | ||
- | if(ret<0) { | ||
- | printk("Unsable to register char device %d\n", ret); | ||
- | return ret; | ||
- | } | ||
- | |||
- | hello_buf = kmalloc(256, GFP_KERNEL); | ||
- | memset(hello_buf,'*',256); | ||
- | printk("Hello kernel: %c\n", hello_buf[0]); | ||
- | return 0; | ||
- | } | ||
- | static void hello_exit(void) | ||
- | { | ||
- | if(hello_buf) { | ||
- | printk("Goodbyte kernel: %c\n", hello_buf[0]); | ||
- | kfree(hello_buf); | ||
- | } | ||
- | unregister_chrdev(187,"hello"); | ||
- | printk(KERN_INFO "Goodbye\n"); | ||
- | } | ||
- | |||
- | module_init(hello_init); | ||
- | module_exit(hello_exit); | ||
- | </code> | ||
- | |||
- | <code bash> | ||
- | #!/bin/bash | ||
- | |||
- | #mknod /dev/hello c 187 0 | ||
- | |||
- | rmmod hello | ||
- | insmod hello.ko | ||
- | cat /dev/hello | ||
- | dmesg | tail | ||
- | </code> | ||
- | ===== Reference ===== | ||
- | * [[https://wwssllabcd.github.io/blog/2012/11/13/how-to-make-linux-module/|一個簡單的 Linux Kernel Module]] | ||
- | * [[https://github.com/torvalds/linux/blob/master/lib/test_debug_virtual.c|virt_to_phys sample]] | ||
- | |||