目录
内存分配是如何完成的?" >内存分配是如何完成的?
第一个系统调用:brk" >第一个系统调用:brk
地址空间布局随机化:ASLR" >地址空间布局随机化:ASLR
第二个系统调用:mmap" >第二个系统调用:mmap
Linux 中内存分配的重要性" >Linux 中内存分配的重要性
首页 系统教程 操作系统 Linux 上内存分配的工作原理

Linux 上内存分配的工作原理

Feb 10, 2024 pm 04:00 PM
linux linux教程 linux系统 linux命令 外壳脚本 嵌入式linux linux入门 linux学习

了解 Linux 内存分配的细节非常重要,尤其是在内核和系统架构中。让我们深入了解 Linux 内存分配并了解幕后发生的事情。

在计算机中,要使进程可执行,就需要将其放置在内存中。为此,必须将字段分配给内存中的进程。内存分配是一个需要注意的重要问题,尤其是在内核和系统架构中。

让我们详细了解一下 Linux 内存分配,并了解幕后发生的事情。

内存分配是如何完成的?

大多数软件工程师不知道这个过程的细节。但如果你是一名系统程序员候选人,你应该对它了解更多。在看分配过程的时候,有必要对 Linux 和glibc库做一个小细节。

当应用程序需要内存时,它们必须从操作系统请求它。来自内核的这个请求自然需要系统调用。您不能在用户模式下自己分配内存。

**malloc()**系列函数负责 C 语言中的内存分配。这里要问的问题是 malloc() 作为 glibc 函数是否进行直接系统调用。

Linux 内核中没有称为 malloc 的系统调用。但是,对于应用程序的内存需求有两个系统调用,它们是brkmmap

由于您将通过 glibc 函数在应用程序中请求内存,您可能想知道此时 glibc 正在使用哪些系统调用。答案是两者兼而有之。

Linux 上内存分配的工作原理

第一个系统调用:brk

每个进程都有一个连续的数据字段。通过 brk 系统调用,增加了决定数据域限制的程序中断值,并执行了分配过程。

尽管使用这种方法分配内存非常快,但并不总是可以将未使用的空间返回给系统。

例如,假设您通过 malloc() 函数为 brk 系统调用分配了五个字段,每个字段大小为 16KB。当您完成其中第二个字段时,无法返回相关资源(解除分配)以便系统可以使用它。因为如果您减少地址值以显示第二个字段的开始位置,并调用 brk,您将完成第三、四个和五个字段的释放。

为了防止这种情况下的内存丢失,glibc 中的 malloc 实现会监控进程数据字段中分配的位置,然后通过 free() 函数指定将其返回给系统,以便系统可以将空闲空间用于进一步的内存分配。

也就是说,在分配了 5 个 16KB 的区域之后,如果用 free() 函数返回第二个区域,过一段时间再请求另一个 16KB 的区域,而不是通过 brk 系统调用扩大数据区域,之前的地址是回来。

但是,如果新请求的区域大于 16KB,则数据区域将通过 brk 系统调用分配新区域来扩大,因为区域 2 无法使用。虽然二号区域没有使用,但由于大小不同,应用程序无法使用它。因为这样的场景,有一种情况叫做内部碎片,实际上你很少能充分利用内存的所有部分。

为了更好地理解,请尝试编译并运行以下示例应用程序:

#include 
#include 
#include 
int main(int argc, char* argv[])
{
        char *ptr[7];
        int n;
        printf("Pid of %s: %d", argv[0], getpid());
        printf("Initial program break   : %p", sbrk(0));
        for(n=0; nprintf("After 5 x 16kB malloc   : %p", sbrk(0));
        free(ptr[1]);
        printf("After free of second 16kB       : %p", sbrk(0));
        ptr[5] = malloc(16 * 1024);
        printf("After allocating 6th of 16kB    : %p", sbrk(0));
        free(ptr[5]);
        printf("After freeing last block        : %p", sbrk(0));
        ptr[6] = malloc(18 * 1024);
        printf("After allocating a new 18kB     : %p", sbrk(0));
        getchar();
        return 0;
}
登录后复制

运行应用程序时,您将获得类似于以下输出的结果:

Pid of ./a.out: 31990
Initial program break   : 0x55ebcadf4000
After 5 x 16kB malloc   : 0x55ebcadf4000
After free of second 16kB       : 0x55ebcadf4000
After allocating 6th of 16kB    : 0x55ebcadf4000
After freeing last block        : 0x55ebcadf4000
After allocating a new 18kB     : 0x55ebcadf4000
登录后复制
Linux 上内存分配的工作原理

带有 strace 的 brk 的输出如下:

brk(NULL)                               = 0x5608595b6000
brk(0x5608595d7000)                     = 0x5608595d7000
登录后复制

如您所见,0x21000 已添加到数据字段的结束地址。您可以从值 0x5608595d7000 中理解这一点。因此分配了大约 0x21000 或 132KB 的内存。

这里有两点需要考虑。第一种是分配超过示例代码中指定的数量。另一个是哪一行代码导致了提供分配的 brk 调用。

地址空间布局随机化:ASLR

当您一个接一个地运行上述示例应用程序时,您每次都会看到不同的地址值。以这种方式随机更改地址空间会使安全攻击的工作变得非常复杂,并提高了软件的安全性。

但是,在 32 位架构中,通常使用 8 位来随机化地址空间。增加位数将不合适,因为剩余位上的可寻址区域将非常低。此外,仅使用 8 位组合不会使攻击者的事情变得足够困难。

另一方面,在 64 位体系结构中,由于可以为 ASLR 操作分配的位太多,因此提供了更大的随机性,并且提高了安全程度。

Linux 内核还支持基于 Android 的设备,并且 ASLR 功能在 Android 4.0.3 及更高版本上完全激活。即使仅出于这个原因,也可以说 64 位智能手机比 32 位版本具有显着的安全优势。

通过使用以下命令暂时禁用 ASLR 功能,之前的测试应用程序每次运行时都会返回相同的地址值:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
登录后复制

要将其恢复到以前的状态,在同一个文件中写入 2 而不是 0 就足够了。

第二个系统调用:mmap

mmap 是 Linux 上用于内存分配的第二个系统调用。通过 mmap 调用,内存中任何区域的空闲空间都映射到调用进程的地址空间。

在以这种方式完成的内存分配中,当您想使用前面 brk 示例中的 free() 函数返回第二个 16KB 分区时,没有机制可以阻止此操作。从进程的地址空间中删除相关的内存段。它被标记为不再使用并返回系统。

因为与使用 brk 相比,使用 mmap 的内存分配非常慢,所以需要分配 brk。

使用 mmap,内存的任何空闲区域都映射到进程的地址空间,因此在该进程完成之前,已分配空间的内容被重置。如果没有以这种方式进行重置,则属于先前使用相关内存区域的进程的数据也可以被下一个不相关的进程访问。这样就不可能谈论系统中的安全性。

Linux 中内存分配的重要性

内存分配非常重要,尤其是在优化和安全问题上。如上面的示例所示,不完全理解此问题可能意味着破坏系统的安全性。

甚至许多编程语言中存在的类似于 push 和 pop 的概念也是基于内存分配操作的。能够很好地使用和掌握系统内存对于嵌入式系统编程和开发安全和优化的系统架构都是至关重要的。

如果您还想涉足 Linux 内核开发,请考虑首先掌握 C 编程语言。

综上所述,Linux 中的内存分配是一个需要注意和理解的重要问题,特别是对于程序员、内核开发人员和系统架构师而言。熟练掌握内存分配可以提高软件性能和安全性,并在嵌入式系统编程和系统架构方面提供更好的支持。同时,C 编程语言的掌握也是涉足 Linux 内核开发的关键。

以上是Linux 上内存分配的工作原理的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1663
14
CakePHP 教程
1420
52
Laravel 教程
1313
25
PHP教程
1266
29
C# 教程
1239
24
Linux体系结构:揭示5个基本组件 Linux体系结构:揭示5个基本组件 Apr 20, 2025 am 12:04 AM

Linux系统的五个基本组件是:1.内核,2.系统库,3.系统实用程序,4.图形用户界面,5.应用程序。内核管理硬件资源,系统库提供预编译函数,系统实用程序用于系统管理,GUI提供可视化交互,应用程序利用这些组件实现功能。

git怎么查看仓库地址 git怎么查看仓库地址 Apr 17, 2025 pm 01:54 PM

要查看 Git 仓库地址,请执行以下步骤:1. 打开命令行并导航到仓库目录;2. 运行 "git remote -v" 命令;3. 查看输出中的仓库名称及其相应的地址。

Linux的主要目的是什么? Linux的主要目的是什么? Apr 16, 2025 am 12:19 AM

Linux的主要用途包括:1.服务器操作系统,2.嵌入式系统,3.桌面操作系统,4.开发和测试环境。Linux在这些领域表现出色,提供了稳定性、安全性和高效的开发工具。

notepad怎么运行java代码 notepad怎么运行java代码 Apr 16, 2025 pm 07:39 PM

虽然 Notepad 无法直接运行 Java 代码,但可以通过借助其他工具实现:使用命令行编译器 (javac) 编译代码,生成字节码文件 (filename.class)。使用 Java 解释器 (java) 解释字节码,执行代码并输出结果。

sublime写好代码后如何运行 sublime写好代码后如何运行 Apr 16, 2025 am 08:51 AM

在 Sublime 中运行代码的方法有六种:通过热键、菜单、构建系统、命令行、设置默认构建系统和自定义构建命令,并可通过右键单击项目/文件运行单个文件/项目,构建系统可用性取决于 Sublime Text 的安装情况。

laravel安装代码 laravel安装代码 Apr 18, 2025 pm 12:30 PM

要安装 Laravel,需依序进行以下步骤:安装 Composer(适用于 macOS/Linux 和 Windows)安装 Laravel 安装器创建新项目启动服务访问应用程序(网址:http://127.0.0.1:8000)设置数据库连接(如果需要)

git软件安装 git软件安装 Apr 17, 2025 am 11:57 AM

安装 Git 软件包括以下步骤:下载安装包运行安装包验证安装配置 Git安装 Git Bash(仅限 Windows)

VSCode怎么用 VSCode怎么用 Apr 15, 2025 pm 11:21 PM

Visual Studio Code (VSCode) 是一款跨平台、开源且免费的代码编辑器,由微软开发。它以轻量、可扩展性和对众多编程语言的支持而著称。要安装 VSCode,请访问官方网站下载并运行安装程序。使用 VSCode 时,可以创建新项目、编辑代码、调试代码、导航项目、扩展 VSCode 和管理设置。VSCode 适用于 Windows、macOS 和 Linux,支持多种编程语言,并通过 Marketplace 提供各种扩展。它的优势包括轻量、可扩展性、广泛的语言支持、丰富的功能和版

See all articles