嵌入式知识点总结 操作系统 专题提升(五)-内存

针对于嵌入式软件杂乱的知识点总结起来,提供给读者学习复习对下述内容的强化。

目录

1.在1G内存的计算机能否malloc(1.2G)?为什么?

2.malloc能申请多大的空间?

3.内存管理有哪几种方式?

4.什么虚拟内存?

5.解释下内存碎片,内碎片,外碎片?

6.解释下虚拟地址,逻辑地址,线性地址,物理地址?

7.虚拟内存置换方法是怎么样的?

8.给你一个类,里面有static,virtual之类的,来说一说这个类的内存分布?

9.假设临界区资源释放,如何保证只让一个线程获得临界区资源而不是都获得?

10.操作系统中的缺页中断是什么?

11.OS缺页置换算法如何实现的?

12.系统调用是什么,你用过哪些系统调用,和库函数有什么区别?

[13.为什么要有page cache,操作系统怎么设计的page cache?](#13.为什么要有page cache,操作系统怎么设计的page cache?)


1.在1G内存的计算机能否malloc(1.2G)?为什么?

在一台拥有1GB内存的计算机上,调用 malloc(1.2G) 是不可能成功的,因为操作系统会检查可用的内存空间。在这种情况下,系统只能分配最多1GB的内存,超出了这个限制,malloc 会返回 NULL,表示分配失败。

这里的原因有几个方面:

物理内存限制:计算机的物理内存只有1GB,操作系统无法为单一进程分配超过这个值的内存。虽然现代操作系统(如Linux、Windows)支持虚拟内存,但虚拟内存并不是无限的。

操作系统的内存管理:即使系统使用虚拟内存,操作系统通常会设置一定的内存限制来避免进程超出可用内存范围,尤其是对于单个进程的内存分配。所以即使你有足够的交换空间(swap space),系统仍会限制进程分配过多内存。

虚拟内存:如果系统启用了虚拟内存,并且交换空间足够大,操作系统可能会允许你申请超过物理内存的内存量。但是,这会导致频繁的磁盘交换,严重影响性能,且并不意味着所有的内存都会被实际分配给进程。

++malloc能够申请的空间大小与物理内存的大小没有直接关系,仅与程序的虚拟地址空间相关。
程序运行时,堆空间只是程序向操作系统申请划出来的一大块虚拟地址空间。应用程序通过malloc申请空间,得到的是在虚拟地址空间中的地址,之后程序运行所提供的物理内存是由操作系统完成的。
本题要申请空间的大小为 1.2G=230x1.2 Byte ,1.2G=(1024*1024*1024)*1.2Byte转换为十六进制约为 4CCCCCCC,这个数值已经超过了 int 类型的表示范围,但还在 unsigned 的表示范围。幸运的是malloc 函数要求的参数为 unsigned 。见下面的示例代码。++

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    char *p;
    const unsigned k = 1024 * 1024 * 1024 * 1.2; // 计算内存大小,1.2GB
    printf("%u\n", k); // 输出计算的内存大小
    p = (char *)malloc(k); // 申请内存
    if (p != NULL)
        printf("ok\n");
    else
        printf("error\n");
    
    free(p); // 释放内存
    return 0;
}

该程序计算 1.2GB 的内存大小并尝试进行内存分配。

在1GB内存的计算机上,通常因为系统的物理内存限制(除非系统配置了非常大的交换空间),malloc 很可能会失败,返回 NULL,然后打印 error

如果系统有足够的内存(或者有足够的交换空间),程序将成功分配内存,并打印 ok

现代操作系统使用虚拟内存机制,允许程序使用比物理内存更大的地址空间。

虚拟内存通过将部分数据存储在磁盘(如交换分区或页面文件)上来扩展可用内存。

因此,即使物理内存不足,malloc(1.2G) 也可能成功,因为操作系统会将部分数据交换到磁盘。

2.malloc能申请多大的空间?

malloc 可以申请多大的空间,取决于多个因素,包括操作系统的内存管理、硬件架构、操作系统的限制和系统配置。下面是一些影响 malloc 可分配内存大小的关键因素:

32位系统 :在32位操作系统中,单个进程的虚拟地址空间通常限制为4GB(理论上是 2^32 字节)。在这种系统上,malloc 申请的最大内存会受到该限制的影响。实际上,由于操作系统和硬件的配置,通常只有2GB或者更少的地址空间可以供进程使用(剩余的内存地址用于操作系统自身),并且受限于内存碎片和内存管理策略。

64位系统 :在64位操作系统中,虚拟地址空间大大增加,理论上支持的内存可以高达2^64 字节,极其庞大。实际上,操作系统和硬件会有一些实际限制(如硬件支持的最大内存、操作系统的配置等)。在64位系统中,malloc 能够申请的空间大大增加,可能达到数TB甚至更多。

Linux :Linux 操作系统中的 malloc 申请内存的最大限制通常受到物理内存、交换空间以及进程最大虚拟内存空间的限制。在64位 Linux 系统上,malloc 的最大内存限制可以非常大(通常由操作系统内核和硬件支持来决定),但也取决于系统配置(如 ulimit 设置、内存映射、虚拟内存设置等)。malloc 的实际限制也可能受到内存碎片化和系统资源的影响。

Windows:Windows 操作系统也支持大内存分配,但其最大分配空间受到物理内存、虚拟内存(例如页面文件的大小)以及系统架构的影响。在32位 Windows 上,单个进程的最大地址空间限制通常为2GB(对于某些配置为3GB),而在64位 Windows 上,理论上支持极大的虚拟内存空间,但仍受硬件和操作系统配置限制。

3.内存管理有哪几种方式?

  1. 连续内存分配(Contiguous Allocation)

概念:所有的进程都在物理内存中占据一个连续的内存区域。

特点:简单高效,但容易造成内存碎片。

类型

单一连续分配:一个进程只占用一个连续的内存区域,适用于短小的程序。

固定分区分配:内存被分为若干个固定大小的区块,进程被分配到适合大小的区块中。

动态分区分配:内存区块大小根据需要动态分配,不固定,但会随着时间推移出现碎片。

优缺点

优点:容易实现,访问效率高。

缺点:随着时间的推移,内存碎片问题严重,可能导致无法找到足够的连续内存。

  1. 非连续内存分配(Non-contiguous Allocation)

概念:进程在内存中的分配不要求是连续的,而是通过地址映射和分页技术来管理。

实现方式

分页(Paging):将内存和进程的地址空间都分为固定大小的块(页),进程的每个页可以在物理内存中的任何位置,不需要连续。

分段(Segmentation):将进程划分为多个逻辑段(如代码段、数据段、堆栈段等),每个段在内存中可以独立分配,段的大小不固定。

优缺点

优点:消除内存碎片问题,灵活性更高。

缺点:需要复杂的内存映射和地址转换,可能引入管理开销。

  1. 虚拟内存管理(Virtual Memory Management)

概念:虚拟内存通过将硬盘的一部分作为扩展内存(交换空间或页面文件),允许程序使用比物理内存更多的内存。

实现方式

页面交换(Paging):将内存分为固定大小的页面,操作系统根据需要将内存页交换到硬盘中,进程运行时只需加载当前需要的页面。

分段交换:将整个段(如代码段)交换到硬盘中,适合较大块的内存管理。

优缺点

优点:程序能够使用比物理内存更多的内存,支持多任务操作。

缺点:访问硬盘时速度较慢,可能引发"交换抖动"(Thrashing),即频繁从硬盘交换数据,导致性能下降。

  1. 内存池管理(Memory Pooling)

概念:内存池将内存预先分配好并组织为一个内存池,进程或线程从池中申请内存。这种方式常用于需要频繁分配和释放内存的场景。

特点:避免频繁的内存分配和释放,提升效率。

优缺点

优点:提高内存分配效率,避免碎片化。

缺点:可能造成内存的浪费,尤其是当内存池的大小过大或过小时。

  1. 伙伴系统(Buddy System)

概念:内存被划分为大小为2的幂次方的块,每个块有一个伙伴,合并和分裂操作通过伙伴来管理,保证内存分配和回收时没有碎片。

特点:内存分配时每次分配2的幂次方大小的内存块,减少内存碎片。

实现:当一个内存块释放时,操作系统会查找其"伙伴"是否空闲,若空闲,则合并成一个更大的内存块。

4.什么虚拟内存?

虚拟内存是一种让程序认为它拥有连续的大内存的技术,实际上程序使用的内存可能分布在不同的物理位置,甚至不完全在内存中。

简单来说,虚拟内存让程序可以使用比实际物理内存更多的内存。操作系统通过将不常用的数据暂时存储到硬盘上的交换空间(swap space)来实现,只有当需要时再将它们加载回内存。

  • 让程序可以使用更多内存,比实际物理内存大。
  • 增强多任务处理能力,让多个程序能并行运行。

5.解释下内存碎片,内碎片,外碎片?

内碎片是分配的内存比需要的内存多,造成空间浪费。

外碎片是内存中有很多小块空闲空间,但这些小块不连续,无法被大内存块使用。

6.解释下虚拟地址,逻辑地址,线性地址,物理地址?

虚拟地址:程序看到的地址,由操作系统管理,跟物理内存无关。

逻辑地址:程序生成的地址(有时和虚拟地址一样),在分段管理中使用。

线性地址:在分页系统中,经过段映射后的地址,还需要分页才能得到物理地址。

物理地址:实际的内存地址,硬件操作的地址,直接对应内存中的位置。

7.虚拟内存置换方法是怎么样的?

虚拟内存的置换方法主要是通过选择合适的页面来腾出内存空间,常见的置换算法有:

FIFO:先来先服务,简单,但可能不够高效。

LRU:选取最久未使用的页面,效果较好。

LFU:选取最少使用的页面,适合访问频率较低的场景。

OPT:理论上最佳,但不可实现。

Random:随机置换,简单但不高效。

实际操作系统会根据不同情况选择适合的置换算法,以平衡性能和效率。

8.给你一个类,里面有static,virtual之类的,来说一说这个类的内存分布?

实例数据:存储在堆或栈中,每个对象有一份副本。

静态成员:类的所有实例共享,存储在数据段中。

虚函数表(Vtable):存储在只读数据区,类中每个对象有一个指向虚函数表的指针(Vptr)。

9.假设临界区资源释放,如何保证只让一个线程获得临界区资源而不是都获得?

要保证 临界区 资源的 互斥访问 ,通常需要使用同步机制,确保在同一时间只有一个线程能访问临界区。最常见的方法是使用 互斥锁(mutex)信号量(semaphore)

互斥锁(Mutex):在进入临界区时,线程会先尝试获取锁,如果锁已经被其他线程占用,当前线程将被阻塞,直到锁被释放。这样,多个线程就不会同时进入临界区。

信号量(Semaphore):信号量控制临界区的资源数量,确保不超过一定数量的线程同时进入临界区。二值信号量通常用于实现互斥锁。

10.操作系统中的缺页中断是什么?

缺页中断是虚拟内存管理中的一个重要概念。当程序访问一个当前不在物理内存中的页面时,会触发缺页中断。操作系统通过捕获这个中断并进行处理,加载所需的页面到内存中,从而让程序继续执行。

触发条件:程序访问的虚拟地址在物理内存中没有对应的页面。

处理过程

  1. 触发缺页中断。
  2. 操作系统暂停程序,查看页面是否在磁盘中的交换空间(Swap Space)或其他地方。
  3. 如果页面在硬盘中,将其加载到内存中。
  4. 更新页表,将虚拟地址映射到新的物理地址。
  5. 继续执行程序。

11.OS缺页置换算法如何实现的?

缺页置换算法是在缺页中断发生时,操作系统决定哪些页面需要被换出,并选择一个合适的页面进行替换。常见的缺页置换算法有:

LRU(Least Recently Used):选择最久未使用的页面进行置换。操作系统可以通过维护一个队列或时间戳来跟踪页面的使用情况,选择最近最少使用的页面换出。

FIFO(First In, First Out):最早加载到内存的页面优先被置换。操作系统维护一个队列,新的页面在队列尾部,最老的页面在队列头部,队列头部的页面会被置换。

OPT(Optimal):理论上最优的算法,选择未来最长时间不会被使用的页面进行置换。缺点是不可实现,因为操作系统无法预测未来的访问模式。

随机置换:操作系统随机选择一个页面进行置换,简单但不一定高效。

12.系统调用是什么,你用过哪些系统调用,和库函数有什么区别?

系统调用(System Call) :系统调用是应用程序与操作系统内核之间的接口。当应用程序需要操作系统提供的服务(如文件操作、进程管理、内存分配等)时,会通过系统调用与操作系统交互。常见的系统调用包括 read(), write(), fork(), exec() 等。

库函数(Library Function):库函数是由程序库提供的预定义函数,它们封装了常见的操作(如数学计算、字符串处理等)。库函数通常是用户空间的代码,直接调用库函数不会进入操作系统内核。

13.为什么要有page cache,操作系统怎么设计的page cache?

Page Cache 是操作系统用来提高磁盘I/O性能的一种机制。它将磁盘文件内容缓存到内存中,避免每次访问文件时都需要从磁盘读取,提高了文件访问的速度。

原因

磁盘访问速度远远低于内存,频繁的磁盘I/O会极大影响性能。

文件内容往往会被多次访问,缓存可以减少重复读取磁盘的开销。

设计

操作系统会在内存中为文件数据保留一个缓存区,这个区域叫做页面缓存(Page Cache)。

当程序访问文件时,操作系统首先检查是否文件的数据已存在于缓存中。如果存在,直接从内存返回数据;如果不存在,操作系统会从磁盘读取数据并缓存到内存中。

采用 LRU 或其他替换算法来管理缓存中的数据,保证高效地使用有限的内存空间。

相关推荐
吴可可1232 小时前
Curve.GetSplitCurves高效分割技巧
算法
用户2367829801682 小时前
Linux iptables 深度解析:从规则匹配到 NAT 转发实战
linux
硅谷秋水2 小时前
Qwen-VLA:跨任务、环境与机器人形态的视觉-语言-动作统一建模
人工智能·深度学习·算法·计算机视觉·语言模型·机器人
CairBin2 小时前
SideSail——Ubuntu 26.04(GNOME 50)侧边栏插件,支持设备信息剪贴板和米家设备简单控制
linux·ubuntu
技术硬汉2 小时前
当前国内2G、3G、4G、5G基站覆盖状况
物联网·5g·信息与通信
howard20053 小时前
3.4 Linux目录操作
linux·目录操作
IronMurphy3 小时前
【算法五十六】84. 柱状图中最大的矩形
算法
fie88893 小时前
matlab打靶法求解两点边值优化问题
开发语言·算法·matlab
Volunteer Technology3 小时前
Flink的DataStream分区操作
大数据·linux·flink