linux/mm/memory.c/do_wp_page and un_wp_page

2023-05-16

void do_wp_page(unsigned long error_code,unsigned long address)
{
#if 0
/* we cannot do this yet: the estdio library writes to code space */
/* stupid, stupid. I really want the libc.a from GNU */
if (CODE_SPACE(address))
do_exit(SIGSEGV);
#endif
// 调用un_wp_page函数来处理写共享页面的问题。这里传给un_wp_page函数
// 的参数是要写的共享页面的物理地址。而参数address是线性地址,所以
// 这个函数的关键技术就是将address这个线性地址转成物理地址并传参给
// un_wp_page函数。
// 线性地址怎么转成物理地址呢?要参考分页内存管理的映射图。在linux0.11
// 的分页内存管理系统中,线性地址被分成三部分:前10bit为页目录表中表项
// 索引,查页目录表可得页表基地址;次10bit为页表中页面索引,查表可得
// 页面基地址,最后12bit为页面内偏移值,可以精确定位到内存的字节单元。
// 因此物理地址和线性地址的转换就要参考这个映射规律了。在这里将线性地址
// address拆开成三份,用前两份来计算合成这个物理地址。具体方法是:
// 首先(address>>10)&0xffc得到address所在页面在其页表中的索引值,其次
// (address>>20)&0xffc得到address所在页表在页目录表中的索引值。而关键就在于
// 物理地址和线性地址的分界线---这个分界线就是页目录表中的表项,也即页表的
// 基地址。所以用address分析索引到了页目录表内,也就和物理地址挂上钩了。只要
// 根据(address>>20)&0xffc这个索引取值得到的页表基地址,就是物理地址的最高10
// bit了,物理地址的次10bit仍然是(address>>10)&0xffc,低12bit是页面内偏移不去
// 论之。
// 写到这里其实不难发现,线性地址和物理地址之所以能够映射,功劳全在
// 页目录表。页目录表很特殊,它处于物理内存0x00000000处,这个位置开始的一页
// 的线性地址和物理地址是重合的。这个重合就为两种地址机制的映射提供了契机。
// 任意给定的线性地址,很容易根据其前10bit在页目录表中找到对应的表项,然后从
// 这个表项中拿出来的就成了物理地址的页表基地址,这样线性地址的后22bit其实一直
// 都是在物理地址区间在使用的。
// 再进一步思考,从线性地址到物理地址很容易映射,那么从物理地址到线性地址能不能
// 实现映射呢?我得出的结论是不能···因为至少这样的映射不唯一,至少在copy_page_tables
// 函数中就实现了两个不同的线性地址对应一个物理地址。实际上也很好理解,只要在
// 页目录表中让两个表项中内容相同,那么这两个表项代表的两个线性地址就对应到同一个
// 物理地址中去了。而我们如果想从物理地址找回来找到对应的线性地址,除非先用这个
// 物理地址的次10bit得到他的页表基地址,然后在页目录表中去遍历它的1024个表项,看看
// 哪个表项中的页表地址和这个地址相同,才能知道这个物理地址反映射回去的线性地址。
// 这样看来,其实通过查一个物理地址在mem_map数组中的引用记录,如果它只被一个进程
// 引用,那么倒是可以通过遍历页目录表来反映射到它的线性地址了。即使它被共享了,也
// 可以通过遍历来得到共享这页物理内存的进程的线性地址,从而得知这些进程是哪几个进程
// 所以刚才的结论是错误的,是可以反映射的,只是麻烦些。不知道实际有没有这种需求
un_wp_page((unsigned long *)
(((address>>10) & 0xffc) + (0xfffff000 &
*((unsigned long *) ((address>>20) &0xffc)))));


}

// un_wp_page即为un_write_protection_page,用来解除内存页面只读的问题
// 该函数被do_wp_page调用。这里的table_entry为一页内存的物理地址
void un_wp_page(unsigned long * table_entry)
{
unsigned long old_page,new_page;


// 内存页面只读有两种情况。一种是该内存页面只被引用了一次,即该页面不是
// 共享页面。(按照我的分析,这种情况就是子进程的只读页面。因为在copy_page_tables
// 内把父子进程的页面都设置成了只读,所以对哪个进行写操作都会触发这个异常
// 最终调用过来。子进程的页面申请后就只被引用过一次,而父进程至少会被引用
// 过两次,所以属于另一种情况了)
old_page = 0xfffff000 & *table_entry;
if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
*table_entry |= 2;
invalidate();
return;
}
// 能执行到这里,即说明是另一种情况,即该页面被引用了多于一次。这种情况应该是用户
// 建立了子进程后先对父进程进行了写操作触发了异常。这种情况下首先要申请新的页面,
// 然后对原页面引用次数减一(我在看copy_page_tables的时候就预料到在处理共享页面时
// 一定要再执行减1操作,现在得到了证实)将新页面的地址先设置为可读写,然后再覆盖掉
// 原地址。最后用copy_page函数将原页面的一页内容复制到新页面内。
if (!(new_page=get_free_page()))
oom();
if (old_page >= LOW_MEM)
mem_map[MAP_NR(old_page)]--;
*table_entry = new_page | 7;
invalidate();
copy_page(old_page,new_page);
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux/mm/memory.c/do_wp_page and un_wp_page 的相关文章

  • 测试linux下磁盘空间不足

    我有一个程序 当写入某个文件的磁盘空间不足时 该程序可能会死掉 我不确定是否是这种情况 我想运行它并查看 但我的测试服务器不会很快耗尽空间 有什么办法可以嘲笑这种行为吗 看起来没有任何方法可以在 Ubuntu 中设置文件夹 文件大小限制 并
  • WaitForSingleObject 是否充当内存屏障?

    昨天一个关于双重检查锁定的问题引发了一系列的想法 让我对一个简单的情况感到不确定 在下面的代码中 是否可以点击printf 不再同步 在这个简单的示例中 这些值可能位于同一缓存行上 因此我认为这种可能性较小 假设一开始可能性 gt 0 如果
  • 为什么 MetaSpace 大小是已用 MetaSpace 的两倍?

    我写了一个程序来模拟MetaSpace OOM 但我发现MetaSpace Size几乎总是两倍大Used MetaSpace Why 我用标志运行我的程序 XX MaxMetaspaceSize 50m 程序抛出OOM时Used Meta
  • 原生 Linux 应用程序可像 ResHacker 一样编辑 Win32 PE

    我想运行自动修改 dll服务 用户提交特定的 dll 我在服务器上修改它 然后用户可以下载 dll的修改版本 是否有任何本机 Linux 应用程序提供常见的 Win32 PE 修改功能 例如图标 字符串 加速器 对话等 至少提供命令行或脚本
  • /proc/PID 文件格式

    我想从中检索一些流程信息 proc目录 我的问题如下 中的文件是否有标准格式 proc PID 例如 有这个proc PID status文件与Name t ProcName在第一行 我可以在其他地方用空格代替这个文件吗 t或者类似的东西
  • 退出 bash 脚本但保持进程运行

    我正在运行服务器 需要使用参数执行以下命令 这些脚本目前工作得很好 但问题是当我运行脚本时我无法返回到控制台 它在控制台中保持运行 如果我强行停止它 那么该过程也会停止 我想继续运行该进程并返回到控制台 bin sh php home st
  • 通过 SSH 将变量传递给远程脚本

    我正在通过 SSH 从本地服务器在远程服务器上运行脚本 首先使用 SCP 复制该脚本 然后在传递一些参数时调用该脚本 如下所示 scp path to script server example org another path ssh s
  • 如何在 Linux 中使用单行命令获取 Java 版本

    我想通过单个命令获取 Linux 中的 Java 版本 我是 awk 的新手 所以我正在尝试类似的事情 java version awk print 3 但这不会返回版本 我将如何获取1 6 0 21从下面的Java版本输出 java ve
  • gcc 不太可能使用宏

    我正在编写一段关键代码 其逻辑大致如下 if expression is true do something with extremely low latency before the nuke blows up This branch i
  • 如何在 Linux x86_64 上模拟 iret

    我正在编写一个基于 Intel VT 的调试器 由于当 NMI Exiting 1 时 iret 指令在 vmx guest 中的性能发生了变化 所以我应该自己处理vmx主机中的NMI 否则 guest会出现nmi可重入错误 我查了英特尔手
  • sqlite 插入需要很长时间

    我正在将不到 200 000 行插入到 sqlite 数据库表中 我只是在终端中通过 sqlite3 使用一个非常简单的 sql 文件 我打赌它已经运行了至少 30 分钟 这是正常现象还是我应该关闭该过程并尝试不同的方法 sqlite中的插
  • Gradle 1.3:build.gradle 不构建类

    这里有一个新问题 我有一个 build gradle 文件apply plugin java在其中 并与 java 项目 包关联 当我跑步时gradle build从命令行我得到 compileJava UP TO DATE process
  • R 未获取用户库

    我有一个带 R 3 6 0 的 Fedora 30 系统 用户库设置在Renviron就像这个 R LIBS USER R LIBS USER R x86 64 redhat linux gnu library 3 6 事实上 它出现在交互
  • 序列化对于对象大小估计可靠吗?

    我使用序列化来估计对象使用的内存量 我已经读过this https stackoverflow com questions 426396 how much memory does a c net object use and this ht
  • 错误:NVIDIA-SMI 失败,因为无法与 NVIDIA 驱动程序通信

    NVIDIA SMI 抛出此错误 NVIDIA SMI 失败 因为无法与 NVIDIA 通信 司机 确保安装了最新的 NVIDIA 驱动程序并且 跑步 我清除了 NVIDIA 并按照提到的步骤重新安装了它here https askubun
  • 如何通过代理将套接字连接到http服务器?

    最近 我使用 C 语言编写了一个程序 用于连接到本地运行的 HTTP 服务器 从而向该服务器发出请求 这对我来说效果很好 之后 我尝试使用相同的代码连接到网络上的另一台服务器 例如 www google com 但我无法连接并从网络中的代理
  • 具有少量父设备属性的 udev 规则

    我需要复杂且通用的udev规则来确定插入任何 USB 集线器的特定端口的 USB 设备 所以 我必须结合设备树不同层的父属性 我有这个 udevadm info query all name dev ttyUSB0 attribute wa
  • Linux 上的 Python 3.6 tkinter 窗口图标错误

    我正在从 Python GUI 编程手册 学习 Python GUI 某项任务要求我通过将以下代码添加到我的配方中来更改窗口图标 Change the main windows icon win iconbitmap r C Python3
  • 如何防止字符串被截留

    我的理解 可能是错误的 是 在 C 中 当你创建一个字符串时 它会被实习到 实习生池 中 这保留了对字符串的引用 以便多个相同的字符串可以共享操作内存 但是 我正在处理很多很可能是唯一的字符串 一旦完成每个字符串 我需要将它们从操作内存中完
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO

随机推荐

  • QEMU搭建U-Boot+Linux+NFS 环境 学习笔记

    使用QEMU搭建U Boot 43 Linux 43 NFS嵌入式开发环境 QEMU简介使用QEMU的事情使用QEMU学习嵌入式的好处驱动开发技能搭建嵌入式基本开发环境基本环境Vmware 43 Ubuntu18 04Vmwaretools
  • brctl使用教程

    使用brctl来操作网桥还是很方便的 xff01 比使用ip命令来操作方便多了 brctl安装 Centos系统 yum install bridge utils Ubuntu系统 Debian系 apt get install bridg
  • IntelliJ IDEA 之 配置JDK 的 4种方式

    一 新建项目前配置JDK 打开idea集成开发环境工具 xff0c 点击File gt Project Structure 如下图 xff1a 在打开的页面中 xff0c 选择SDKs属性 xff0c 并点击中间的加号 43 选择JDK x
  • STM32如何在LCD上显示单词、文字、图片等

    本文将介绍STM32F103R6如何在LCD12864上显示文字图片 注 xff1a 本文中用到的字模软件 xff0c 我放在了文章末尾 xff0c 点击链接即可下载 xff0c 是绿色版软件 xff0c 解压即可使用 xff01 点击下载
  • JAVA之Lambda表达式详解

    文章目录 一 基本概念1 背景2 Lambda表达式的语法3 函数式接口 二 Lambda表达式的基本使用1 无返回值函数式接口2 有返回值函数接口3 语法精简 三 变量捕获1 匿名内部类2 Lambda的变量捕获 四 Lambda在集合当
  • 【CUDA】安装CUDA

    文章目录 1 搜索CUDA xff0c 进入官网2 选择以前的版本3 选择指定的版本4 选择操作系统并下载5 以管理员身份运行安装CUDA6 测试是否安装成功 1 搜索CUDA xff0c 进入官网 2 选择以前的版本 3 选择指定的版本
  • 计算机组成原理---系统总线

    文章目录 1 总线的基本概念2 总线的分类2 1 片内总线2 2 系统总线2 2 1 系统总线的定义2 2 2 按照系统总线传输信息的分类2 2 3 通信总线 3 总线的性能指标3 1 总线标准 4 总线结构4 1 单总线结构4 2 多总线
  • 计算机组成原理---总线带宽的计算

    end
  • QT之窗口背景颜色和图片设置

    设置窗口 窗体的背景图片 第一种 xff1a 定义一个函数 xff0c 使用QPalette和QPixmap 在 h文件定义一个私有的函数声明 xff1a void resizeEvent QpesizeEven event 然后右键跳到定
  • linux/mm/memory.c/put_page

    put page用来完成物理页面与一个线性地址页面的挂接 xff0c 从而将一个 线性地址空间内的页面落实到物理地址空间内 xff0c copy page tables函数 只是为一个进程提供了在线性地址空间的一个页表及1024页内存 xf
  • 解决keil软件*** Error: Project ‘first‘ requires ‘C51‘ Toolchain which is not installed.

    在安装好了 xff08 破解 xff09 后的MDK环境后依然无法编译 xff0c 出现 Error Project first requires C51 Toolchain which is not installed 软件安装 一 介绍
  • 计算机网络:第四章习题

    简答题 amp 计算题 4 03 作为中间设备 xff0c 转发器 网桥 路由器和网关有何区别 xff1f 答 xff1a 转发器 xff1a 它工作在物理层 xff0c 主要起信号的放大整形和延迟传输距离的作用 网桥 xff1a 工作在数
  • 【mysql 5.7】最左原则 & like查询%在前为什么不走索引

    文章目录 1 问题的引入2 非覆盖索引场景下为什么 在前为什么不走索引参考 xff1a 1 问题的引入 在非覆盖索引场景下 xff0c 大家知道Mysql索引有最左原则 xff0c 所以通过 like 39 XX 39 查询的时候一定会造成
  • Bottom-Up and Top-Down

    top down xff1a 在模式识别中使用了上下文信息 xff08 机器的处理方式 xff09 举例 xff1a 当你看到一张字迹潦草难以辨认的手写文本时 xff0c 你可以利用整个文本来辅助你理解其中含义 xff0c 而不是每个字单独
  • 浅层与深层、局部与全局、低级与高级特征的辨析

    浅层网络与深层网络 浅层网络更注重于细节信息 深层网络更注重于语义信息 浅层网络 xff1a 一般感受野较小 xff0c 能够利用更多的细粒度特征信息 xff0c 而且此时特征图每个像素点对应的感受野重叠区域还很小 xff0c 这就保证了网
  • ARM交叉编译工具链安装和使用教程【图文并茂】

    ARM交叉编译工具链安装和使用教程 图文并茂 1 交叉编译安装 2 交叉编译使用 1 交叉编译安装 下载 由于嵌入式板卡的软硬件是定制的 xff0c 因此针对其平台开发的程序所需要的编译器也必须与之相匹配 xff1a GEC6818开发板交
  • 关于Jquery index()方法的文字详细解析

    关于Jquery index xff08 xff09 方法的文字详细解析 此函数返回的是一个元素的索引位置 xff0c 索引位置从零开始 若带参数 xff0c index参数可以直接传入jquery选择器进行元素选择 也可以传入字符串进行元
  • ESP8266

    ESP8266 一 xff0c 物联网介绍 物联网 xff0c 即IOT xff08 internet of things xff09 是用网络将万物互联 xff0c 如将汽车 xff0c 温度计 xff0c 咖啡杯等都可以连接到互联网 x
  • ES8新特性之async函数与await表达式(常见疑惑解答)

    说明 xff1a 在学习了async和await后 xff0c 很多人往往不知道这两个人是干什么的 xff0c 对于这两个重要角色的使用方式和原理都比较模糊 xff0c 下面为大家介绍这两个角色的语法 xff0c 后面附有两个小例子 xff
  • linux/mm/memory.c/do_wp_page and un_wp_page

    void do wp page unsigned long error code unsigned long address if 0 we cannot do this yet the estdio library writes to c