四级页表结构

现在的64位Linux系统中,并没有使用全部的64位地址空间,而是使用其低48位,高16位并没有使用.

其中

39至47这9位用于索引PGD(page global directory),其中读取的值是PUD(page upper directory)的地址

30至38这9位用于索引PUD以获取PMD(page middle directory)的地址

21至29这9位用于索引PMD以获取PTE(the lowest level page table)的地址

12至20这9位用于索引PTE以获数据所在物理page frame的地址

最后的12位是page frame 的偏移,用于定位具体的数据所在地址

图形表示如图:

注:

原来的三级页表为:PGD-->PMD-->PTE

二级页表为:PGD(PGD)-->PTE

获取系统的page size

$ getconf PAGE_SIZE

获取当前内核使用多少级的页表结构

通过编译内核的config文件,搜索CONFIG_PGTABLE_LEVELS,既可以知道使用的是多少级的页表结构

内核地址空间中物理地址与虚拟地址的转换

#include <asm/io.h>

static inline void *phys_to_virt(phys_addr_t address);//__pa

static inline phys_addr_t virt_to_phys(volatile void *address)__va

读取任意程序内存实现

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/mm_types.h>
#include <asm/pgtable.h>

static ulong data_addr = 0;
static int data_len = 0;
static int target_pid = 0;

module_param(data_addr,ulong,S_IRUGO);
module_param(data_len,int,S_IRUGO);
module_param(target_pid,int,S_IRUGO);

static int __init main_init(void)
{
    struct task_struct *task;
    char *vaddr;
    int retval = 0;
    int i = 0;
    pgd_t *pgd = NULL;
    pud_t *pud = NULL;
    pmd_t *pmd = NULL;
    pte_t *pte = NULL;
    unsigned long paddr = 0;
    unsigned long page_addr = 0;
    unsigned long page_offset = 0;

    if(data_addr == 0 || data_len == 0 || target_pid == 0){
        printk("insmod main <data_addr=?> <data len=?> <target_pid=?>\n");
        return 0;
    }

    printk("data_addr:0x%lX, data_len:%d, target_pid:%d\n",data_addr,data_len,target_pid);

    for_each_process(task){
        if(task->pid == target_pid)
        {
            printk("find task:%s\n",task->comm);
            retval = 1;
            break;
        }
    }

    if(retval == 0){
        printk("not find task\n");
        return -1;
    }

    pgd = pgd_offset(task->mm,data_addr);
    if(pgd_none(*pgd)){
        printk("not mapped in pgd\n");
        return -1;
    }

    pud = pud_offset((p4d_t*)pgd,data_addr);
    if(pud_none(*pud)){
        printk("not mapped in pud\n");
        return -1;
    }

    pmd = pmd_offset(pud,data_addr);
    if(pmd_none(*pmd)){
        printk("not mapped in pmd\n");
        return -1;
    }

    pte = pte_offset_kernel(pmd,data_addr);
    if(pte_none(*pte)){
        printk("not mapped in pte\n");
        return -1;
    }

    page_addr = pte_val(*pte) & PTE_PFN_MASK;
    page_offset = (data_addr) & (0xFFF);
    paddr = page_addr | page_offset;

    vaddr = __va(paddr);

    for(i = 0;i<data_len;i++){
        printk("0x%X('%c')\n",vaddr[i],vaddr[i]);
    }

    return 0;
}

static void __exit main_exit(void)
{
}

module_init(main_init);
module_exit(main_exit);
MODULE_LICENSE("GPL");

makefile:

obj-m := main.o

all:
    make -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) modules
clean:
    make -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) clean

参考资料

How The Kernel Manages Your Memory:

https://manybutfinite.com/post/how-the-kernel-manages-your-memory/

Five-level page tables:

https://lwn.net/Articles/717293/

Page Table Management:

https://www.kernel.org/doc/gorman/html/understand/understand006.html

Page table

https://github.com/lorenzo-stoakes/linux-vm-notes/blob/master/sections/page-tables.md

Virtual memory map

https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt

Linux 内存管理分析

https://www.jianshu.com/p/fc719d1cfbc2

Linux中的虚拟地址转换物理地址实现

http://lzz5235.github.io/2014/12/10/linux.html

Linux x64 -- 内核程序(驱动程序)读取任意进程数据实现的更多相关文章

  1. 12_通过 CR3 切换_读取指定进程数据

    注意: cr3 切换 ,导致eip 指向的页面,改变为对应cr3 的页面:所以代码也变了:这里需要将这部分代码放入公共区域. 解决: 使用 类似前面 山寨 systemfastcallentry 的方 ...

  2. 一个I/O线程可以并发处理N个客户端连接和读写操作 I/O复用模型 基于Buf操作NIO可以读取任意位置的数据 Channel中读取数据到Buffer中或将数据 Buffer 中写入到 Channel 事件驱动消息通知观察者模式

    Tomcat那些事儿 https://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng==&mid=2650860016&idx=2&sn=549 ...

  3. linux服务器开发二(系统编程)--进程相关

    进程相关的概念 程序与进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(CPU.内存.打开的文件.设备.锁等等). 进程,是一个抽象的概念,与操作系统原理联系紧密.进程是活跃的程序,占用系 ...

  4. Linux下触摸屏驱动程序分析

    [摘要: 本文以linux3.5--Exynos4412仄台,剖析触摸屏驱动焦点内容.Linux下触摸屏驱动(以ft5x06_ts为例)须要懂得以下学问: 1. I2C协定 2. Exynos4412 ...

  5. Linux中的两种守护进程stand alone和xinetd

    Linux中的两种守护进程stand alone和xinetd --http://www.cnblogs.com/itech/archive/2010/12/27/1914846.html#top 一 ...

  6. Linux内核分析(四)----进程管理|网络子系统|虚拟文件系统|驱动简介

    原文:Linux内核分析(四)----进程管理|网络子系统|虚拟文件系统|驱动简介 Linux内核分析(四) 两天没有更新了,上次博文我们分析了linux的内存管理子系统,本来我不想对接下来的进程管理 ...

  7. 【转载】 java利用snmp4j包来读取snmp协议数据(Manager端)

    https://www.cnblogs.com/xdp-gacl/p/4187089.html http://doc.okbase.net/yuanfy008/archive/265663.html ...

  8. [转帖]Linux系统进程的知识总结,进程与线程之间的纠葛...

    Linux系统进程的知识总结,进程与线程之间的纠葛... https://cloud.tencent.com/developer/article/1500509 当一个程序开始执行后,在开始执行到执行 ...

  9. Linux的启动过程及init进程

    Linux下有三个特殊进程: idle进程(pid=0)idle进程其前身是系统创建的第一个进程,0号进程,也唯一一个没有通过fork()或者kernel_thread产生的进程,由系统自动创建,运行 ...

随机推荐

  1. 【Java并发编程】22、Exchanger源码解析(JDK1.7)

    Exchanger是双向的数据传输,2个线程在一个同步点,交换数据.先到的线程会等待第二个线程执行exchangeSynchronousQueue,是2个线程之间单向的数据传输,一个put,一个tak ...

  2. java中自己常犯的错误汇总

    package debug; /** 1.定义一个公共的动物类,包含名字.年龄.颜色和吃饭东西方法 2.定义一个猫类,继承动物类,同时拥有玩游戏的本领 3.定义一个狗类,继承动物类,同时拥有看门的本领 ...

  3. 二进制值和十六进制字符串相互转换的C++代码

    #include <iostream> #include <string> #include <stdint.h> using namespace std; str ...

  4. python字典按照value进行排序

    先说几个解决的方法,具体的有时间再细说 d = {'a':1,'b':4,'c':2} 字典是这个,然后要对字典按照value进行排序 方法一: sorted(d.items(),key = lamb ...

  5. css兼容问题(一)

    开头语:不用就忘,还是自己乖乖的记笔记吧! 正文开始:    (一)如果你的页面对IE7兼容没有问题,又不想大量修改现有代码,同时又能在IE8中正常使用,微软声称,开发商仅需要在目前兼容IE7的网站上 ...

  6. Python编程-从入门到实践 Eric Matthes 著 袁国忠 译 - - 第二章 动手试一试

    因为第一章的动手试一试基本都是探索性的,所以直接进入第二章. # 2.2 动手试一试 # 2_1 简单消息: 将一条消息存储到变量中,再将其打印出来. message = 'python 编程从入门到 ...

  7. CSS总结div中的内容垂直居中的五种方法

    一.行高(line-height)法 如果要垂直居中的只有一行或几个文字,那它的制作最为简单,只要让文字的行高和容器的高度相同即可,比如: p { height:30px; line-height:3 ...

  8. Jmeter在非GUI(命令行)模式下生成测试报告

    根据各大招聘网站上的需求来看,熟悉Jmeter做性能测试已经几乎成为必要条件了. 那么今天在这个给大家安利一波,怎么使用Jmeter在非GUI(命令行)模式下生成测试报告呢?? 条件准备: 1.Jme ...

  9. android recovery 升级之USB设备挂载

    Recovery升级过程,通常会从两个地方获取升级包update.zip升级,一般在线升级,会把升级包下载到cache分区,本地升级会从usb或者tf卡中升级.本文讨论下,本地USB升级时,无法挂载U ...

  10. eclipse下载教程

    Eclipse 是一个开放源代码的.基于 Java 的可扩展开发平台. Eclipse 是 Java 的集成开发环境(IDE),当然 Eclipse 也可以作为其他开发语言的集成开发环境,如C,C++ ...