进程地址空间地址转换为物理地址
2011-08-08 20:31
225 查看
kernel代码
Makefile
user space代码
/* * To test kernel's scheduler * Date:2011/8/8 13:04 * ### wait queue ### */ #include <linux/init.h> #include <linux/list.h> #include <linux/module.h> #include <linux/kmod.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/kthread.h> #include <linux/sched.h> #include <linux/wait.h> #include <linux/kallsyms.h> #include <linux/uaccess.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <mach/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/page.h> #include <asm/mman.h> #include <asm/pgtable.h> #include <asm/uaccess.h> #include <asm/cacheflush.h> #include <mach/bitfield.h> //#define SYNC_DEBUG /* <1> no define SYNC_DEBUG [ 2160.339202] [bloop, 68]i = 0 [ 2160.445648] [bloop, 68]i = 0 [ 2160.554992] [bloop, 68]i = 0 [ 2160.664337] [bloop, 68]i = 0 [ 2160.773712] [bloop, 68]i = 0 [ 2160.883087] [bloop, 68]i = 0 [ 2160.992462] [bloop, 68]i = 0 [ 2161.100952] [bloop, 68]i = 0 [ 2161.210357] [bloop, 68]i = 0 [ 2161.319702] [bloop, 68]i = 0 [ 2161.429962] [bloop, 68]i = 1 [ 2161.539337] [bloop, 68]i = 1 [ 2161.648773] [bloop, 68]i = 1 <2> define SYNC_DEBUG [ 2160.339202] [bloop, 68]i = 0 [ 2161.648773] [bloop, 68]i = 1 [ 2161.648773] [bloop, 68]i = 2 */ /* ### Get data from user space(not copy_from_user api) ### # insmod /data/thread_test.ko [ 7366.976959] [thread_init, 201] # # # # # /data/vm_test[ 7385.550354] VM test open [ 7385.553436] VM_TEST_GET_VADDR: 0x0007eb78 vaddress: 0x0007eb78 str: yugui.hu@gmail.com [ 7385.557708] str:yugui.hu@gmail.com [ 7385.565307] paddr: 0xc5f62b78 [ 7385.568267] [ 7385.568267] =======Data======== [ 7385.572998] yugui.hu@gmail.com [ 7385.576049] =======Data======= q Byte!! */ struct task_struct *kthreadA; struct task_struct *kthreadB; static int i = 0; #ifdef SYNC_DEBUG static wait_queue_head_t wait; #endif // IOCTL #define VM_TEST_GET_VADDR 0 #define KSYM_NAME_LEN 128 #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \ 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1) /* #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 #define SCHED_BATCH 3 #define SCHED_IDLE 5 */ static int aloop(void *x) { struct sched_param param = { .sched_priority = 0 }; sched_setscheduler(current, SCHED_NORMAL, ¶m); while (!kthread_should_stop()) { msleep(1000); i++; #ifdef SYNC_DEBUG wake_up_interruptible(&wait); #endif } return 0; } static int bloop(void *x) { struct sched_param param = { .sched_priority = 2 }; sched_setscheduler(current, SCHED_FIFO, ¶m); while (!kthread_should_stop()) { #ifdef SYNC_DEBUG interruptible_sleep_on(&wait); #endif printk("[%s, %d]i = %d\n", __func__, __LINE__, i); msleep(100); } return 0; } static unsigned long uva_to_pa(struct mm_struct *mm, unsigned long addr) { unsigned long ret = 0UL; pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; pgd = pgd_offset(mm, addr); if (!pgd_none(*pgd)) { pud = pud_offset(pgd, addr); if (!pud_none(*pud)) { pmd = pmd_offset(pud, addr); if (!pmd_none(*pmd)) { pte = pte_offset_map(pmd, addr); if (!pte_none(*pte) && pte_present(*pte)) { /* Use hard PTE */ pte = (pte_t *)((u32)pte - 2048); if(pte) ret = (*pte & 0xfffff000) | (addr & 0xfff); } } } } return ret; } static int vm_test_open( struct inode * inode, struct file * file ) { printk("VM test open\n"); return 0; } static int vm_test_ioctl( struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg ) { void __user *argp = (void __user *)arg; unsigned long vaddr; unsigned long paddr; unsigned char str[20] = {0}; switch (cmd) { case VM_TEST_GET_VADDR: printk("VM_TEST_GET_VADDR: 0x%08x\n", (unsigned long)argp); /* output data from user space */ copy_from_user(str, argp, 18); /* !!!删除这个函数后,uva_to_pa不能得到物理地址,还在研究中(缺页异常) */ printk("str:%s\n", str); /* Get physical address */ struct mm_struct *mm = current->mm; paddr = uva_to_pa(mm, vaddr); if (paddr == 0) printk("Can't find physical address!\n"); else printk("paddr: 0x%08x\n", paddr); printk("\n=======Data========\n"); unsigned long vpp = ioremap_nocache(paddr, 18); int i = 0; for (i = 0; i < 18; i++) { printk("%c", *(volatile unsigned char *)(vpp + i)); } printk("\n=======Data=======\n"); return 0; default: return -EINVAL; } } static struct file_operations vm_test_fops = { .owner = THIS_MODULE, .open = vm_test_open, .ioctl = vm_test_ioctl, }; static struct miscdevice vm_test_misc_device = { .minor = MISC_DYNAMIC_MINOR, .name = "VM-TEST", .fops = &vm_test_fops, }; static int thread_init(void) { int err = 0; printk("[%s, %d]\n", __func__, __LINE__); #ifdef SYNC_DEBUG init_waitqueue_head(&wait); #endif //kthreadA = kthread_run(aloop, NULL, "thread-A"); //kthreadB = kthread_run(bloop, NULL, "thread-B"); err = misc_register(&vm_test_misc_device); if (err != 0) printk("misc register device failed!\n"); return 0; } static void thread_exit(void) { #ifdef SYNC_DEBUG wait_queue_t *curr, *next; char str[KSYM_SYMBOL_LEN] = {0}; #endif misc_deregister(&vm_test_misc_device); printk("[%s, %d]\n", __func__, __LINE__); //kthread_stop(kthreadA); mdelay(200); #ifdef SYNC_DEBUG list_for_each_entry_safe(curr, next, &(wait.task_list), task_list) { memset(str, 0 , KSYM_SYMBOL_LEN); kallsyms_lookup((unsigned long)curr->private, NULL, NULL, NULL, str); printk("waiting thread name: %s\n", str); } wake_up_interruptible(&wait); #endif //kthread_stop(kthreadB); } module_init(thread_init); module_exit(thread_exit); MODULE_LICENSE("GPL");
Makefile
# Makefile example ARCH ?= arm CROSS_COMPILE ?= arm-none-linux-gnueabi- KERNELDIR ?= /KERNEL_OUT ifneq ($(KERNELRELEASE),) obj-m := thread_test.o # Otherwise we were called directly from the command line; invoke the kernel build system. else default: $(MAKE) -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules endif
user space代码
/* * file : vm_test.c * * How to use it: * ./vm_test */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/time.h> #include <string.h> #define DEVICE "/dev/VM-TEST" #define VM_TEST_GET_VADDR 0 char str[20]= "yugui.hu@gmail.com"; int main(int argc, char *argv[]) { int fd = 0; char chr = 0; fd = open(DEVICE, O_RDWR); if (fd < 0) { printf("Can't open the %s\n", DEVICE); return -1; } printf("vaddress: 0x%08x str: %s\n", (unsigned long)str, str); ioctl(fd, VM_TEST_GET_VADDR, str); while (1) { chr = getchar(); if (chr == 'q') { printf("Byte!!\n"); return 0; } } return 0; }
相关文章推荐
- 设某计算机的逻辑地址空间和物理地址空间均为128KB,按字节编址。若某进程最多需要6页数据存储空间,页面大小为1KB,操作系统采用固定分配局部置换策略为该进程分配4个页框(物理块)。
- 为什么把进程的地址空间分为逻辑地址空间和物理地址空间?
- 在用户态进行虚拟空间地址向物理空间地址的转换
- 用户空间的虚拟地址如何转换得到实际的物理地址
- 在用户态进行虚拟空间地址向物理空间地址的转换
- 在用户态进行虚拟空间地址向物理空间地址的转换
- 用户态进程的虚拟地址如何转换成物理地址
- 在用户态进行虚拟空间地址向物理空间地址的转换
- linux驱动中物理地址的空间转换
- Linux 内核空间虚拟地址和物理地址相互转换
- 虚拟地址、线性地址和物理地址的转换
- Linux开发心得总结8 - 虚地址转换为物理地址
- 将虚拟地址转换成物理地址
- 两个进程访问同样的逻辑地址物理地址为何不同
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- Linux_分页管理机制(线性地址转换到物理地址)
- 进程虚拟地址空间之数据分区存放【转】
- 进程的虚拟地址空间分配概述
- 逻辑地址与物理地址的转换
- 进程地址空间和虚拟地址空间