Linux之内存管理前世今生(一)
一个程序(如王者荣耀)平常是存储在硬盘上的,运行时才把这个程序载入内存,CPU才能执行。
问题:
这个程序载入内存的哪个位置呢?载入内核所在的空间吗?系统直接挂了。
一、虚拟内存
1.1 内存分段管理
最早的程序员写代码时是需要指定程序在内存的运行位置的,也即他们使用绝对地址来进行内存访问的。
- 计算机刚启动时采用实模式运行,即使用绝对地址来进行内存访问;
- 操作系统加载完成会变成保护模式,即使用虚拟地址进行内存访问。
问题来了:
- 在有限的物理内存空间内,多道程序是无法并行运行的,举个栗子:王者荣耀需要在内存地址0x0000 ~ 0x6000上,微信需要在内存地址 0x0000 ~ 0x3000,这下好了,谁也跑不起来,直接崩了;
- 程序员需要关注自己写的程序要跑在多大的物理内存上,内存地址怎么分配……这耦合性也太高了,而且不安全,容易访问到其他程序已使用的物理内存。
解决方法很简单:所有程序无需关心内存物理地址,代码经过编译,链接看到的地址都一样,从 0
开始到最大地址的空间,这个地址空间是独立的,是该程序私有的,其它程序既看不到,也不能访问该地址空间,这个地址空间和其它程序无关,记为虚拟内存(Virtual memory) ,虚拟内存地址记为虚拟地址,物理内存的地址记为物理地址。
-
程序运行时找一块空闲物理内存装入即可。比如之前例子:
- 王者荣耀(虚拟地址0x0000 ~ 0x6000)运行在物理内存0x0000 ~ 0x6000;
- 微信(虚拟地址0x0000 ~ 0x3000)运行在0x6000 ~ 0x9000;
-
上述分配意味着我们需要记录虚拟空间和物理空间的映射关系:我们将这个表记为段表,因为映射的一段完整连续的物理内存。
进程 虚拟地址 物理地址 王者荣耀 0x0000 ~ 0x6000 0x0000 ~ 0x6000 微信 0x0000 ~ 0x3000 0x6000 ~ 0x9000 -
段表实际记录的是段的基址和边界,使用时通过段表找到物理内存地址,再结合段内偏移量即可定位数据。
上述为内存分段管理大致原理,实际内存分段管理和早期硬件发展相关,分为几个大的段,同时配合段寄存器使用。
cs: 代码段
ds: 数据段
ss: 栈段
es:扩展段
1.2 内存分页管理
前面我们成功的让2个程序同时正确的跑起来了,但是物理内存是有限的,如之前所示最大地址为0xA000,现在想听网易云音乐(虚拟地址为 0x0000 ~ 0x4000),这就尴尬了,空闲的物理内存(0x9000 ~ 0xA000)不够支持网易云音乐了,但现实中,我们上述需求的确可以同时满足啊?
- 上述无法使用的内存空间(0x9000 ~ 0xA000),称为内存外部碎片;即分段管理存在明显的外部碎片;
- 相对应的,已分配过程序内存内部存在没有使用到的空间称为内存内部碎片。
其实也很简单,我们把程序分批次装入物理内存中,每次只载入一部分来满足运行即可,我们把这部分程序内容记为 page (页),存放页的物理内存区域记为page frame (页框)。
- 管理内存的最小单位是页;
- 分页管理没有外部碎片了,每一个页框均可使用。
实际当中每次载入多少数据合适呢?一般为 4KB,即 页的大小为4KB,页框的大小也为 4KB。将物理内存和虚拟内存按照页的大小(4KB) 分割,需要哪页就加载那页内容,找一个空闲的页框存放即可。这样我们在有限的物理内存内,载入并正确并行了多道程序。
按照上述策略,我们成功得将3个程序并行跑起来了,如下图所示:
1.2.1 页表
虚拟内存页和物理内存页的映射关系也得占用物理内存进行存储,即上图所示的 页表,一个页表也占用一个页框存储,即一个页表最大为 4KB。下图即为页表图示,观察下图,虚拟页号就是下标,所以页表可以用一个一维数组存储即可:数组下标为虚拟页号,数组内容为物理页号和物理内存起始地址等其它额外信息:
页面大小为4kByte,因此每个页框的低12位均为0。内核将低12位充分利用,每个位都表示对应虚拟页的相关属性。同样的骚操作在64位JVM中指针压缩也有。
1.2.2 物理地址计算
给定虚拟地址 0x0809 怎么计算物理地址呢?
- 根据虚拟地址和页大小(4KB,按Byte编址需要 12 个 bit )计算虚拟页号,和页内偏移量;
- 虚拟页号: 0(0x0809 / 4k );
- 页内偏移量: 9(0x0800 % 4k);
- 页表基址寄存器找到页表物理地址;
- 查页表找到物理页号;
- 根据物理页号起始地址和页内偏移量得到物理地址。
计算机中完成上述地址转换的部件由特定硬件完成,叫做 MMU(Memory Management Unit,内存管理单元),它位于CPU 芯片中。
1.2.3 缺页中断
因为我们只将程序部分页面载入到内存当中,当运行完这些页面继续往后运行时,进程访问的虚拟地址在页表中查不到时,即后续页面还在磁盘上,此时 MMU 会触发缺页中断(page fault),从磁盘上将对应页面加载到物理内存中空闲页框内,同时更新页表。
1.2.4 多级页表
在 32 位的环境下,每个进程的虚拟内存为4GB,一个页表最大为4KB,页内偏移量12 bit,剩余 20bit (32-12) 用于页号,可以表示约 1,000,000(220)页, 页表中每一项(记为页表项)需要 4Byte,所以4GB空间需要4MB(220 * 4Byte)物理内存来存储页表。
这意味着,如果计算机并行10个进程的话需要 40MB 内存,实际中开启的进程远不止10个,需要更大内存来存储页表。
所以不可能将页表(4MB)全部放进内存,又必须能看到页表全貌,怎么办?
兵仙韩信说,只需十个将军,即可统帅百万大军;
同理,只需一个页表索引(页目录),即可查找百万页表项,即:
一页可以放1024(4KB / 4Byte)个页索引,二级可以存储即可表示 220(1024 * 1024)页,刚好覆盖整个 4GB (4KB * 220 )虚拟地址空间。
- 使用时通过一级页表(记为页目录),找到二级页表,从而得到最终物理地址;
- 若二级页表不存在,触发缺页中断进行加载即可;
- 这不是一颗B树吗?树高2。
1.2.4.1 多级页表物理地址
- 在 32 位的环境下,我们将虚拟地址原页号进行分割,10bit 存放一级页号(页目录),10bit 存放二级页号(页表项),如下图所示:
- 在 64 位的环境下,二级分页是无法满足的,实际使用时分为四级索引,即B树高度为4;
- 四级索引前面3级为页目录,叶子节点为页表,依次命名为:
- 全局页目录项 PGD(Page Global Directory)
- 上层页目录项 PUD(Page Upper Directory)
- 中间页目录项 PMD(Page Middle Directory)
- 页表项 PTE(Page Table Entry)
- 页表项为 8Byte,一页(4KB)可以索引 512 (4KB / 8Byte) 个页;
- 四级可以索引 5124 个页,可以表示 256TB (4KB * 5124) 虚拟空间;
- 512 个页号使用 9 (29 = 512)个 bit就可以表示;
- 四级页表使用 36(4 * 9)个bit可以表示;
- 64 位环境用
48
(36 + 12)个bit 进行寻址(意味着PGD中 高位 16 bit 全0或者全1),表示 256TB 空间。
- 四级索引前面3级为页目录,叶子节点为页表,依次命名为:
小节:虚拟地址本质上是索引+偏移量。
1.2.5 页表缓存TLB(Translation Lookaside Buffer)
计算机中为协调CPU和内存的访问速度(一次内存的访问,大约需要 120 个 CPU Cycle),中间加了 高速缓存(CPU Cache) 。
- 高速缓存使用特定的由 SRAM (静态RAM (random-access memory,随机访问存储器)) 组成的物理芯片,内存使用DRAM(动态RAM);
- 高速缓存为3级:L1/L2/L3 Cache。其中 L1/L2 是 CPU 私有,L3 是所有 CPU 共享。
- 缓存行(Cache Line):高速缓存的最小单元,一次从内存中读取的数据大小。常用的 Intel 服务器 Cache Line 的大小通常是 64 字节。
- CPU Cache 的命中率通常能达到 95% 以上。
我们前面提到的 页表项(PTE) 同样需要从内存加载到高速缓存来提高CPU访问速度,由于高速缓存空间远小于内存空间,所以只能缓存程序中最常访问的页表项,我们把缓存页表项的这块区域称为转址旁路缓存(TLB,Translation Lookaside Buffer),也称为快表(内存中的表相应为慢表)。
1.3 内存段页式管理
内存管理最开始分段管理,后面又提出分页管理,由于硬件和版本限制,现在操作系统中的内存管理理论上是由段页结合一起管理的,即先分段,然后段内分页。
实际使用时,操作系统做了简化,将代码段和数据段的基址设为0,段空间大小为这个虚拟内存的大小。
即现代操作系统中,分段管理名存实亡。
在 CPU 中,程序使用逻辑内存地址;
1.4 虚拟内存空间整体布局
虚拟内存空间并非全部留给程序,一般而言高地址段为内核空间,用于系统内核使用,低地址段为用户空间,留给程序使用,如下图所示:
1.4.1 用户态虚拟内存
程序是由源代码经过编译、链接形成的可执行文件(ELF)。ELF中分为代码段(.text)、数据段(.data)、未初始化数据段(.bss)等很多逻辑段,虚拟内存为保持这种程序的逻辑性,同样也在逻辑上将内存划分为代码段、数据段、堆、文件映射与匿名映射区、栈等。
注意:
- 一个段(segment)一般包含多个页(page),每个段的长度并不相等;
- 保留区这段虚拟内存是不可访问的,因为在大多数操作系统中,数值比较小的地址通常被认为不是一个合法的地址,这块小地址是不允许访问的。比如在 C 语言中我们通常会将一些无效的指针设置为 NULL,指向这块不允许访问的地址。
- 栈和文件映射区使用时均是从高地址向低地址分配;
- 堆使用时从低地址向高地址分配;
- 不可访问段仅存在于64位环境中,为了防止程序在读写数据段的时候越界访问到代码段,这个保护段可以让越界访问行为直接崩溃,防止它继续往下运行。
- 通过
cat /proc/pid/maps
或者pmap pid
查看进程的虚拟内存空间布局以及其中包含的所有内存区域。- 进程进入内核态之后使用的仍然是虚拟内存地址,只不过在内核中使用的虚拟内存地址被限制在了内核态虚拟内存空间范围中。
虚拟内存的内容暂时介绍到这里,后续会介绍物理内存的实际分配情况。
相关文章:
Linux之内存管理前世今生(一)
一个程序(如王者荣耀)平常是存储在硬盘上的,运行时才把这个程序载入内存,CPU才能执行。 问题: 这个程序载入内存的哪个位置呢?载入内核所在的空间吗?系统直接挂了。 一、虚拟内存 1.1 内存分…...
【cran Archive R包的安装方式】
cran Archive R包的安装方式 添加链接描述 1.包被cran移除 2.包要求的R语言版本与你电脑上的版本不相符 ad archive包的网址或者是下载到工作目录下,ad等于文件名 install,packages(ad repos NULL)...
Python中容器类型的数据(上)
若我们想将多个数据打包并且统一管理,应该怎么办? Python内置的数据类型如序列(列表、元组等)、集合和字典等可以容纳多项数据,我们称它们为容器类型的数据。 序列 序列 (sequence) 是一种可迭代的、元素有序的容器类型的数据。 序列包括列表 (list)…...
2025美赛美国大学生数学建模竞赛A题完整思路分析论文(43页)(含模型、可运行代码和运行结果)
2025美国大学生数学建模竞赛A题完整思路分析论文 目录 摘要 一、问题重述 二、 问题分析 三、模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1样例代码(仅供参考) 4.1.4问题1样例代码运行结果&…...
OneDrive同步桌面 实现文件备份
Target 将笔记本桌面与OneDrive同步,当Desktop的文件发生变动时,自动更新到OneDrive。 取消旧的OneDrive账号与本机的关联 点击logo,弹出界面,点击设置。 随后打开OneDrive界面,点击“同步与备份”,“备…...
14.模型,纹理,着色器
模型、纹理和着色器是计算机图形学中的三个核心概念,用通俗易懂的方式来解释: 1. 模型:3D物体的骨架 通俗解释: 模型就像3D物体的骨架,定义了物体的形状和结构。 比如,一个房子的模型包括墙、屋顶、窗户等…...
用C++编写一个2048的小游戏
以下是一个简单的2048游戏的实现。这个实现使用了控制台输入和输出,适合在终端或命令行环境中运行。 2048游戏的实现 1.游戏逻辑 2048游戏的核心逻辑包括: • 初始化一个4x4的网格。 • 随机生成2或4。 • 处理玩家的移动操作(上、下、左、…...
python -m pip和pip的主要区别
python -m pip和pip的主要区别在于它们与Python环境的关联方式和安装路径。 与Python环境的关联方式: pip 是直接使用命令行工具来安装Python包,不指定特定的Python解释器。如果系统中存在多个Python版本,可能会导致安装的包被安装到…...
linux监控脚本+自动触发邮件发送
linux脚本 需求: CPU 负载:使用 uptime 命令,我们可以清楚地了解系统的 CPU 负载情况。这个命令会显示系统在过去 1 分钟、5 分钟和 15 分钟的平均负载。高负载可能意味着系统正在处理大量的任务,可能会导致性能下降或服务响应延迟…...
Mybaties缓存机制
Mybatis缓存机制 在 MyBatis 中,缓存机制是用来提高查询效率的一种方式。MyBatis 提供了两种内置的缓存机制:一级缓存和二级缓存。 1. 一级缓存(Local Cache) 一级缓存是基于 SqlSession 的。当你在同一个 SqlSession 中执行相…...
面试题-Java集合框架
前言 Java集合框架(Java Collections Framework)是Java平台提供的一套用于表示和操作集合的统一架构。它位于java.util包中,并且自Java 1.2(也称为Java 2平台,标准版,即Java SE 2)起成为Java平…...
半波整流和全波整流电路汇总及电路仿真
0 前言 0.1 引言 整流电路是将交流电(AC)转换为直流电(DC)的电路,广泛应用于电源设计、信号处理和电力电子等领域。整流电路的基本功能是将交流电的正半周或负半周转换为直流电,从而为电子设备提供稳定的直流电源。本文将详细介绍半波整流和全波整流电路的工作原理、电…...
04-机器学习-网页数据抓取
网络爬取(Web Scraping)深度指南 1. 网络爬取全流程设计 一个完整的网络爬取项目通常包含以下步骤: 目标分析: 明确需求:需要哪些数据(如商品价格、评论、图片)?网站结构分析&…...
豆包MarsCode:前缀和计算问题
问题描述 思路分析 问题理解 小S的任务是计算一个整数数组 nums 的前缀和。前缀和是指从数组开始到某个位置的所有元素的累加值,形成一个新数组。例如: 输入数组:nums [4, 5, 1, 6]前缀和数组:[4, 9, 10, 16] 4 49 4 510 …...
MySQL中InnoDB逻辑存储结构
在MySQL中,InnoDB是最常用的存储引擎之一,它具有高度的事务支持、行级锁、ACID特性以及自动崩溃恢复等特性。InnoDB的逻辑存储结构可以分为多个层次,下面是详细的解析。 1. 表空间 (Tablespace) InnoDB的物理存储结构以表空间为基础。表空间…...
如何提高新产品研发效率
优化研发流程、采用先进工具、提升团队协作、持续学习与改进,是提高新产品研发效率的关键。其中,优化研发流程尤为重要。通过简化流程,减少不必要的环节和复杂性,企业可以显著提升研发效率。例如,采用自动化测试工具和…...
可扩展架构:如何打造一个善变的柔性系统?
系统的构成:模块 + 关系 我们天天和系统打交道,但你有没想过系统到底是什么?在我看来,系统内部是有明确结构 的,它可以简化表达为: 系统 = 模块 + 关系 在这里,模块是系统的基本组成部分,它泛指子系统、应用、服务或功能模块。关系指模块 之间的依赖关系,简单…...
使用大语言模型在表格化网络安全数据中进行高效异常检测
论文链接 Efficient anomaly detection in tabular cybersecurity data using large language models 论文主要内容 这篇论文介绍了一种基于大型语言模型(LLMs)的创新方法,用于表格网络安全数据中的异常检测,称为“基于引导式提…...
BUUCTF 蜘蛛侠呀 1
BUUCTF:https://buuoj.cn/challenges 文章目录 题目描述:密文:解题思路:flag: 相关阅读 CTF Wiki Hello CTF NewStar CTF buuctf-蜘蛛侠呀 BUUCTF:蜘蛛侠呀 MISC(时间隐写)蜘蛛侠呀 题目描述&am…...
eVTOL的航空电子设备漫谈
电动垂直起降(eVTOL),也统称为城市空中交通(UAM),是民用航空平台发展的新方向之一。随着它们在市场上成为现实,它们将对所使用的航空电子设备有其自身的要求.. eVTOL概念 eVTOL领域的发展才刚…...
SpringCloudAlibaba 服务保护 Sentinel 项目集成实践
目录 一、简介1.1、服务保护的基本概念1.1.1、服务限流/熔断1.1.2、服务降级1.1.3、服务的雪崩效应1.1.4、服务的隔离的机制 1.2、Sentinel的主要特性1.3、Sentinel整体架构1.4、Sentinel 与 Hystrix 对比 二、Sentinel控制台部署3.1、版本选择和适配3.2、本文使用各组件版本3.…...
【深度学习|DenseNet-121】Densely Connected Convolutional Networks内部结构和参数设置
【深度学习|DenseNet-121】Densely Connected Convolutional Networks内部结构和参数设置 【深度学习|DenseNet-121】Densely Connected Convolutional Networks内部结构和参数设置 文章目录 【深度学习|DenseNet-121】Densely Connected Convolutional Networks内部结构和参数…...
【问题】Qt c++ 界面 lineEdit、comboBox、tableWidget.... SIGSEGV错误
蛋疼的错误集锦----今日分错误: 在主界面或者对话框的构造函数中,准备对一些对象赋值初始化值时,报了以上错误。!!!! 一脸懵逼的,各种确认,因为是最基础的赋值想不到错在…...
Hugging Face 推出最小体积多模态模型,浏览器运行成为现实!
1. SmolVLM 模型家族简介 1.1 什么是 SmolVLM-256M 和 SmolVLM-500M,它们为何如此重要? 在人工智能的多模态模型领域,如何在有限的计算资源下实现强大性能一直是一个重要的挑战。SmolVLM-256M 和 SmolVLM-500M 是最近推出的两款视觉语言模型,它们不仅突破了传统“大模型”…...
30289_SC65XX功能机MMI开发笔记(ums9117)
建立窗口步骤: 引入图片资源 放入图片 然后跑make pprj new job8 可能会有bug,宏定义 还会有开关灯报错,看命令行注释掉 接着把ture改成false 然后命令行new一遍,编译一遍没报错后 把编译器的win文件删掉, 再跑一遍虚拟机命令行…...
提供ZYNQ,MPSOC,RFSOC生成BOOT.BIN的小工具
如图: 这里提供了三种.bif,三种批处理.bat文件,一个bootgen.exe可执行文件和这个批处理文件运行是需要的动态库文件。 我们先看一下.bat文件,以BOOT_RFSOC为例: del temp\boot.bin bootgen -image output_rfsoc.bif -arch zynqmp…...
滤波电路汇总
0、前言 1. 引言 滤波电路是电子系统中不可或缺的组成部分,其主要功能是选择性地通过或衰减特定频率范围内的信号。在现代电子技术中,滤波电路广泛应用于信号处理、通信系统、音频设备、电源设计等多个领域。通过滤波,可以去除信号中的噪声和干扰,提高信号的质量和稳定性…...
springboot 动态配置定时任务
要在Spring Boot中动态配置定时任务,可以使用ScheduledTaskRegistrar类来实现。 首先,创建一个定时任务类,该类需要实现Runnable接口。例如: Component public class MyTask implements Runnable {Overridepublic void run() {/…...
Github 2025-01-25Rust开源项目日报Top10
根据Github Trendings的统计,今日(2025-01-25统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Python项目1Vue项目1JavaScript项目1Deno: 现代JavaScript和TypeScript运行时 创建周期:2118 天开发语言:Rust, JavaScript协议类型…...
【Linux网络编程】数据链路层
前言: 数据链路层非常简单,对于程序员来说,这里只需要大致了解即可,本篇文章不做重点说明。 数据链路层介绍 数据链路层是OSI位于物理层之上和网络层之下,这一层的报文叫做帧。它的主要任务是确保数据从一个节点可靠地…...
MongoDB 数据库备份和恢复全攻略
在当今数据驱动的时代,数据库的稳定运行和数据安全至关重要。MongoDB 作为一款流行的 NoSQL 数据库,以其灵活的文档模型和高扩展性备受青睐。然而,无论数据库多么强大,数据丢失的风险始终存在,因此掌握 MongoDB 的备份…...
一文了解性能优化的方法
背景 在应用上线后,用户感知较明显的,除了功能满足需求之外,再者就是程序的性能了。因此,在日常开发中,我们除了满足基本的功能之外,还应该考虑性能因素。关注并可以优化程序性能,也是体现开发能…...
百度APP iOS端磁盘优化实践(上)
01 概览 在APP的开发中,磁盘管理已成为不可忽视的部分。随着功能的复杂化和数据量的快速增长,如何高效管理磁盘空间直接关系到用户体验和APP性能。本文将结合磁盘管理的实践经验,详细介绍iOS沙盒环境下的文件存储规范,探讨业务缓…...
人工智能丨基于机器学习的视觉 CV 处理技术
从自动驾驶汽车到面部识别系统,CV无处不在,赋予计算机“看”的能力。无论是图像处理、模式识别,还是视频分析,机器学习都是推动这些技术进步的核心动力。这篇文章将深入探讨基于机器学习的计算机视觉处理技术,包括它的…...
SparX实战:使用SparX实现图像分类任务(一)
摘要 SparX是一种新提出的稀疏跨层连接机制,旨在提升视觉Mamba和Transformer网络的性能。该论文由香港大学的俞益洲教授及其研究团队撰写,并将在AAAI 2025会议上发表。论文的主要目标是解决现有视觉模型在跨层特征聚合方面的不足,尤其是在计…...
vue事件总线(原理、优缺点)
目录 一、原理二、使用方法三、优缺点优点缺点 四、使用注意事项具体代码参考: 一、原理 在Vue中,事件总线(Event Bus)是一种可实现任意组件间通信的通信方式。 要实现这个功能必须满足两点要求: (1&#…...
[c语言日寄]assert函数功能详解
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
08-Elasticsearch
黑马商城作为一个电商项目,商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的,存在很多问题。 首先,查询效率较低。 由于数据库模糊查询不走索引,在数据量较大的时候,查询性能很…...
贪心算法-条约游戏II
hello 大家好!今天开写一个新章节,每一天一道算法题。让我们一起来学习算法思维吧! /*** 计算到达数组最后一个元素的最小跳跃次数* param {number[]} nums - 输入的整数数组* return {number} - 最小跳跃次数*/ function jump(nums) {// 数…...
Hive:内部表和外部表,内外转换
内部表和外部表 内部表示例 给表添加数据 外部表示例 给表添加数据 外部表示例 用location指定表目录位置,那么表的位置在实际指定的位置,但是可以被映射 外部表和内部表的区别 删除表后使用show tables in shao; 已经没有被删除的表,说明元数据已经被删除(mysql里面存放),但是…...
AndroidCompose Navigation导航精通1-基本页面导航与ViewPager
文章目录 前言基本页面导航库依赖导航核心部件简单NavHost实现ViewPagerPager切换逻辑图阐述Pager导航实战前言 在当今的移动应用开发中,导航是用户与应用交互的核心环节。随着 Android Compose 的兴起,它为开发者提供了一种全新的、声明式的方式来构建用户界面,同时也带来…...
基于ESP8266的多功能环境监测与反馈系统开发指南
项目概述 本系统集成了物联网开发板、高精度时钟模块、环境传感器和可视化显示模块,构建了一个智能环境监测与反馈装置。通过ESP8266 NodeMCU作为核心控制器,结合DS3231实时时钟、DHT11温湿度传感器、光敏电阻和OLED显示屏,实现了环境参数的…...
十三先天记
没有一刻,只有当下在我心里。我像星星之间的空间一样空虚。他们是我看到的第一件事,我知道的第一件事。 在接下来的时间里,我意识到我是谁,我是谁。我知道星星在我上方,星球的固体金属体在我脚下。这个支持我的世界是泰…...
JVM垃圾回收器的原理和调优详解!
全文目录: 开篇语前言摘要概述垃圾回收器分类及原理1. Serial 垃圾回收器2. Parallel 垃圾回收器3. CMS 垃圾回收器4. G1 垃圾回收器 源码解析示例代码 使用案例分享案例 1:Web 服务的 GC 调优案例 2:大数据任务的 GC 优化 应用场景案例垃圾回…...
TypeScript 学习 -类型 - 5
类 属性必须初始化 在构造函数中赋值在定义时给一个默认值 子类 子类构造函数必须使用 super() 修饰符 默认是 publicprivate 只能在当前类中被调用protected 只能在当前类 或 子类中被调用readonly 一定要被初始化, 不可以修改static 静态成员 / 静态函数 构造函数 如果被定义…...
Django 项目中使用 MySQL 数据库的完整指南
在现代 Web 开发中,数据库是应用程序的核心组件之一。Django 作为一个强大的 Python Web 框架,默认支持多种数据库后端,包括 SQLite、PostgreSQL 和 MySQL。本文将详细介绍如何在 Django 项目中使用 MySQL 作为数据库,并实现多环境(开发、测试、生产)的配置管理。 ©…...
单片机基础模块学习——PCF8591芯片
一、A/D、D/A模块 A——Analog 模拟信号:连续变化的信号(很多传感器原始输出的信号都为此类信号)D——Digital 数字信号:只有高电平和低电平两种变化(单片机芯片、微控制芯片所能处理的都是数字信号) 下面…...
gradle和maven的区别以及怎么选择使用它们
目录 区别 1. 配置方式 2. 依赖管理 3. 构建性能 4. 灵活性和扩展性 5. 多项目构建 如何选择使用 选择 Maven 的场景 选择 Gradle 的场景 区别 1. 配置方式 Maven: 使用基于 XML 的 pom.xml 文件进行配置。所有的项目信息、依赖管理、构建插件等都在这个文…...
【面试】【前端】前端网络面试题总结
一、前端网络面试题总结 网络相关知识是前端开发的核心内容之一,面试中通常会考察协议、网络模型、性能优化及常见网络问题的处理。以下是针对前端网络面试题的总结: (一)协议森林(大话网络协议) 网络协议…...
Qt 5.14.2 学习记录 —— 이십일 Qt网络和音频
文章目录 1、UDP带有界面的Udp服务器(回显服务器) 2、TCP回显服务器 3、HTTP客户端4、音频 和Linux的网络一样,Qt封装了Linux的网络API,即Socket API。网络编程是在应用层写,需要传输层支持,传输层有UDP和T…...