原文:Hack The Virtual Memory: C strings & /proc - Holberton

翻译:RobotCode俱乐部

介绍

这是一系列关于虚拟内存的小文章/教程中的第一篇。我们的目标是学习一些计算机基础知识,但是是以一种不同的、更实际的方式。对于第一部分,我们将使用/proc来查找和修改运行进程的虚拟内存中包含的变数(在本例中是ASCII字元串),并在此过程中学习一些很酷的东西。

虚拟内存

在计算中,虚拟内存是一种同时使用硬体和软体实现的内存管理技术。它将程序使用的内存地址(称为虚拟地址)映射到计算机内存中的物理地址。主内存(进程所见)以连续地址空间或连续段的集合的形式出现。操作系统管理虚拟地址空间,并将实际内存分配给虚拟内存。CPU中的地址转换硬体,通常称为内存管理单元或MMU,自动将虚拟地址转换为物理地址。操作系统中的软体可以扩展这些功能,以提供超过实际内存容量的虚拟地址空间,从而可以使用比计算机中实际存在的内存更多的内存。

虚拟内存的主要好处包括使应用程序不必管理共享内存空间,由于内存隔离而提高了安全性,并且能够使用分页技术使用比物理上可用的更多的内存。

在第2章中,我们将深入讨论更多细节,并对虚拟内存中的内容和位置进行一些事实检查。现在,这里有一些关键点,你应该知道:

  • 每个进程都有自己的虚拟内存
  • 虚拟内存的数量取决于系统的体系结构
  • 每个操作系统处理虚拟内存的方式不同,但是对于大多数现代操作系统,进程的虚拟内存是这样的:

如图所示,高内存地址中存放:

  • 命令行参数和环境变数
  • 栈,「向下」增长。这可能看起来违反直觉,但这是在虚拟内存中实现堆栈的方式

在低内存地址,你可以找到:

  • 你的可执行文件(比这稍微复杂一些,但这足以理解本文的其余部分)
  • 堆,「向上」生长。堆是动态分配的内存的一部分(即包含使用malloc分配的内存)。

另外,请记住虚拟内存与RAM是不同的。

C程序

让我们从这个简单的C程序开始,探索字元串到底存在虚拟内存的哪个位置:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/**
* main - uses strdup to create a new string, and prints the
* address of the new duplcated string
*
* Return: EXIT_FAILURE if malloc failed. Otherwise EXIT_SUCCESS
*/
int main(void)
{
char *s;

s = strdup("Holberton");
if (s == NULL)
{
fprintf(stderr, "Cant allocate mem with malloc
");
return (EXIT_FAILURE);
}
printf("%p
", (void *)s);
return (EXIT_SUCCESS);
}

在继续之前,花点时间想一想。你认为strdup如何创建字元串「Holberton」的副本?你如何证实?

strdup

strdup必须创建一个新字元串,因此它首先必须为它预留空间。函数strdup可能正在使用malloc。快速浏览一下手册页就可以确认:

在继续之前,花点时间想一想。根据我们前面关于虚拟内存的讨论,你认为重复字元串将位于何处?在高或低内存地址?

可能在较低的地址(堆中)。让我们编译并运行我们的小C程序来测试我们的假设:

复制的字元串位于地址0x80e5008。太好了。但这是一个低或高地址?

进程的虚拟内存有多大

进程的虚拟内存大小取决于你的系统架构。在这个例子中,我使用一个32位的机器,所以理论上每个进程的虚拟内存的大小是2 ^ 32位元组。理论上,可能的最高内存地址是0xFFFFFFFF,最低内存地址是0x0。

0x80e5008与0xFFFFFFFF相比很小,所以重复的字元串可能位于较低的内存地址。在查看proc文件系统时,我们将能够确认这一点)。

proc文件系统

如果您列出/proc目录的内容,您可能会看到很多文件。我们将集中讨论其中两项:

/proc/[pid]/ mem

/proc/[pid] /maps

mem

太棒了!那么,我们可以访问和修改任何进程的整个虚拟内存吗?

maps

这意味著我们可以查看/proc/[pid]/mem文件来定位正在运行的进程的堆。如果可以从堆中读取,就可以定位要修改的字元串。如果我们可以写堆,我们可以用我们想要的替换这个字元串。

我们通过cat /proc/[pid]/maps再次确认,字元串属于内存的哪个段中:

程序里加了暂停,让其停在此处,方便我们查看maps

--未完待续,下篇讨论如何修改堆中的数据

由于本人水平有限,翻译必然有很多不妥的地方,欢迎指正。

同时,欢迎关注下方微信公众号,一起交流学习:)

推荐阅读:
相关文章