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

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

目录

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?


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 。见下面的示例代码。

#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)

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

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

类型

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

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

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

优缺点

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

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

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

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

实现方式

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

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

优缺点

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

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

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

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

实现方式

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

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

优缺点

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

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

4. 内存池管理(Memory Pooling)

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

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

优缺点

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

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

5. 伙伴系统(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 或其他替换算法来管理缓存中的数据,保证高效地使用有限的内存空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/967872.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Lucene 中的并发错误:如何修复乐观并发失败

作者&#xff1a;来着 Elastic Benjamin Trent 及 Ao Li 感谢 CMU PASTA 实验室开发的确定性并发测试框架 Fray&#xff0c;我们找到了一个棘手的 Lucene 漏洞并将其修复。 是的&#xff0c;另一个修复错误博客。但这个故事有一个转折&#xff0c;一位开源英雄突然出现并拯救了…

redis 缓存击穿问题与解决方案

前言1. 什么是缓存击穿?2. 如何解决缓存击穿?怎么做?方案1: 定时刷新方案2: 自动续期方案3: 定时续期 如何选? 前言 当我们使用redis做缓存的时候,查询流程一般是先查询redis,如果redis未命中,再查询MySQL,将MySQL查询的数据同步到redis(回源),最后返回数据 流程图 为什…

【分布式理论9】分布式协同:分布式系统进程互斥与互斥算法

文章目录 一、互斥问题及分布式系统的特性二、分布式互斥算法1. 集中互斥算法调用流程优缺点 2. 基于许可的互斥算法&#xff08;Lamport 算法&#xff09;调用流程优缺点 3. 令牌环互斥算法调用流程优缺点 三、三种算法对比 在分布式系统中&#xff0c;多个应用服务可能会同时…

【车载项目】 systemui下拉负一屏界面,通过语音输入:“中文模式/英文模式“,会闪现一下负一屏下层的画面

1、背景 【操作步骤】负一屏界面&#xff0c;语音输入&#xff1a;“中文模式/英文模式” 【预期结果】显示正常 【实际结果】 会闪现一下负一屏下层的文字 【发生概率】必现 systemui下拉负一屏界面&#xff0c;通过语音输入&#xff1a;“中文模式/英文模式”&#xff0c;会…

CSS 渐变效果详解——线性渐变与径向渐变

在现代前端开发中&#xff0c;CSS 渐变被广泛应用于网页背景、按钮、图形等元素的渲染。相较于使用图片&#xff0c;实现渐变可以减少资源请求&#xff0c;同时也更灵活。今天我们主要介绍两种常用的渐变类型&#xff1a;线性渐变&#xff08;Linear Gradient&#xff09;与径向…

【愚公系列】《Python网络爬虫从入门到精通》001-初识网络爬虫

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…

如何借鉴GitHub开源项目进行LabVIEW开发

在设备开发过程中&#xff0c;许多开发者选择借鉴GitHub等平台上的开源项目&#xff0c;特别是当目标程序没有LabVIEW版本时。比如&#xff0c;在本例中&#xff0c;我们看到一个开源的Micro-Manager项目&#xff0c;它主要使用Java、C、Python等编程语言。对于LabVIEW开发者来…

大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡

大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡 背景 前端开发接口请求&#xff0c;调试&#xff0c;联调&#xff0c;接入数据&#xff0c;前端必不可少工具&#xff0c;postman是一个非常好…

CSS3+动画

浏览器内核以及其前缀 css标准中各个属性都要经历从草案到推荐的过程&#xff0c;css3中的属性进展都不一样&#xff0c;浏览器厂商在标准尚未明确的情况下提前支持会有风险&#xff0c;浏览器厂商对新属性的支持情况也不同&#xff0c;所有会加厂商前缀加以区分。如果某个属性…

Docker Compose介绍及安装使用MongoDB数据库详解

在现代容器化应用部署中&#xff0c;Docker Compose是一种非常实用的工具&#xff0c;它允许我们通过一个docker-compose.yml文件来定义和运行多容器应用程序。然而&#xff0c;除了Docker之外&#xff0c;Podman也提供了类似的工具——Podman Compose&#xff0c;它允许我们在…

防火墙是什么?详解网络安全的关键守护者

当今信息化时代&#xff0c;企业和个人在享受数字生活带来的便利时&#xff0c;也不可避免地面对各种潜在的风险。防火墙作为网络安全体系中的核心组件&#xff0c;就像一道牢不可破的防线&#xff0c;保护着我们的数据和隐私不受外界威胁的侵害。那么防火墙是什么&#xff1f;…

畅游Diffusion数字人(16):由音乐驱动跳舞视频生成

畅游Diffusion数字人(0):专栏文章导航 前言:从Pose到跳舞视频生成的工作非常多,但是还没有直接从音乐驱动生成的工作。最近字节跳动提出了MuseDance,无需复杂的动作引导输入(如姿势或深度序列),从而使不同专业水平的用户都能轻松进行灵活且富有创意的视频生成。 目录 贡…

机器学习常用包matplotlib篇(一)简单图像绘制

前言 Matplotlib 是支持 Python 语言的开源绘图库&#xff0c;简单且完善。 一、环境配置 1.环境设置 在 Notebook 环境绘图时&#xff0c;需先运行 %matplotlib inline 命令&#xff0c;将绘制图形嵌入当前页面。在桌面环境绘图&#xff0c;无需上述命令&#xff0c;而是在…

深入理解指针初阶:从概念到实践

一、引言 在 C 语言的学习旅程中&#xff0c;指针无疑是一座必须翻越的高峰。它强大而灵活&#xff0c;掌握指针&#xff0c;能让我们更高效地操作内存&#xff0c;编写出更优化的代码。但指针也常常让初学者望而生畏&#xff0c;觉得它复杂难懂。别担心&#xff0c;本文将用通…

如何利用DeepSeek开源模型打造OA系统专属AI助手

利用DeepSeek开源模型打造OA系统专属AI助手&#xff0c;可以显著提升办公效率&#xff0c;增强信息检索和管理能力。 注册与登录DeepSeek平台 访问DeepSeek官网 访问DeepSeek的官方网站DeepSeek。使用电子邮件或手机号码注册账号并登录。 获取API Key 登录DeepSeek平台&am…

jupyter notebook中3种读图片的方法_与_图片翻转(上下翻转,左右翻转,上下左右翻转)

已有图片cat.jpg 相对于代码的位置&#xff0c;可以用./cat.jpg进行读取。 下面是3种读图片的方法。 1.python读图片-pillow 图片文件不适合用open去读取 用open读图片&#xff0c;易引发UnicodeDecodeError: gbk codec cant decode byte 0xff in position 0: illegal multib…

软考高级《系统架构设计师》知识点(一)

计算机硬件 校验码 码距&#xff1a;就单个编码A:00而言&#xff0c;其码距为1&#xff0c;因为其只需要改变一位就变成另一个编码。在两个编码中&#xff0c;从A码到B码转换所需要改变的位数称为码距&#xff0c;如A:00要转换为B:11&#xff0c;码距为2。一般来说&#xff0c;…

【原创精品】基于Springboot3+Vue3的学习计划管理系统

大家好&#xff0c;我是武哥&#xff0c;最近给大家手撸了一个基于SpringBoot3Vue3的学习计划管理系统&#xff0c;可用于毕业设计、课程设计、练手学习&#xff0c;系统全部原创&#xff0c;如有遇到网上抄袭站长的&#xff0c;欢迎联系博主~ 项目演示视频 https://www.bili…

从零到一:我的元宵灯谜小程序诞生记

缘起&#xff1a;一碗汤圆引发的灵感 去年元宵节&#xff0c;我正捧着热腾腾的汤圆刷朋友圈&#xff0c;满屏都是"转发锦鲤求灯谜答案"的动态。看着大家对着手机手忙脚乱地切换浏览器查答案&#xff0c;我突然拍案而起&#xff1a;为什么不做一个能即时猜灯谜的微信…

RAG 在智能答疑中的探索

一、背景 得物开放平台是一个把得物能力进行开放&#xff0c;同时提供给开发者提供 公告、应用控制台、权限包申请、业务文档等功能的平台。 面向商家&#xff1a;通过接入商家自研系统。可以实现自动化库存、订单、对账等管理。 面向ISV &#xff1a;接入得物开放平台&#…