Linux内存管理:高端内存的映射方式(共6篇)由网友“水帘洞小狗”投稿提供,小编在这里给大家带来Linux内存管理:高端内存的映射方式,希望大家喜欢!
篇1:linux 高端内存映射方式
1.1 内核地址空间(线性空间)分布
(1) 直接映射区:线性空间中从3G开始最大896M的区间,为直接内存映射区,该区域的线性地址和物理地址存在线性转换关系:线性地址=3G+物理地址,linux 高端内存映射方式
。(2) 动态内存映射区:该区域由内核函数vmalloc来分配,特点是:线性空间连续,但是对应的物理空间不一定连续。vmalloc分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。
(3) 永久内存映射区:该区域可访问高端内存。访问方法是使用alloc_page(_GFP_HIGHMEM)分配高端内存页或者使用kmap函数将分配到的高端内存映射到该区域。
(4) 固定映射区:该区域和4G的顶端只有4k的隔离带,其每个地址项都服务于特定的用途,如ACPI_BASE等。
说明:
注意用户空间当然可以使用高端内存,而且是正常的使用,内核在分配那些不经常使用的内存时,都用高端内存空间(如果有),所谓不经常使用是相对来说的,比如内核的一些数据结构就属于经常使用的,而用户的一些数据就属于不经常使用的。用户在启动一个应用程序时,是需要内存的,而每个应用程序都有3G的线性地址,给这些地址映射页表时就可以直接使用高端内存。
而且还要纠正一点的是:那128M线性地址不仅仅是用在这些地方的,如果你要加载一个设备,而这个设备需要映射其内存到内核中,它也需要使用这段线性地址空间来完成,否则内核就不能访问设备上的内存空间了。
总之,内核的高端线性地址是为了访问内核固定映射以外的内存资源。进程在使用内存时,触发缺页异常,具体将哪些物理页映射给用户进程是内核考虑的事情。在用户空间中没有高端内存这个概念。
1.2 高端内存映射
高端内存映射含义为:将线性地址空间 (范围从PAGE_OFFSET + 896M 至4G的最后128M)映射到 896M以上的物理页框。如下图所示:
高端内存映射有三种方式(都是非直接映射):1.2.1 映射到“内核动态映射空间”(非连续内存区映射)
这种方式很简单,因为通过 vmalloc ,在内核“动态映射空间”申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说高端内存有可能映射到“内核动态映射空间 ”中,
1.2.2 永久内核映射
如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?
内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START ,用于映射高端内存。在 2.4 内核上,这个地址范围是 4G-8M 到 4G-4M 之间。这个空间起叫“内核永久映射空间”或者“永久内核映射空间”这个空间和其它空间使用同样的页目录表,对于内核来说,就是 swapper_pg_dir,对普通进程来说,通过 CR3 寄存器指向。通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。通过 kmap(), 可以把一个 page 映射到这个空间来。由于这个空间是 4M 大小,最多能同时映射 1024 个 page。因此,对于不使用的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来。永久内存映射允许建立长期映射。
1.2.3 临时映射
内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为“固定映射空间”在这个空间中,有一部分用于高端内存的临时映射。
这块空间具有如下特点:
1、每个 CPU 占用一块空间
2、在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的 km_type 中。当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。
通过 kmap_atomic() 可实现临时映射。可以用在中断处理函数和可延迟函数的内部,从不阻塞。因为临时内存映射是固定内存映射的一部分,一个地址固定给一个内核成分使用。
篇2:Linux内存管理:高端内存的映射方式
高端内存是指物理地址大于 896M 的内存,
对于这样的内存,无法在“内核直接映射空间”进行映射。
为什么?
因为“内核直接映射空间”最多只能从 3G 到 4G,只能直接映射 1G 物理内存,对于大于 1G 的物理内存,无能为力。
实际上,“内核直接映射空间”也达不到 1G, 还得留点线性空间给“内核动态映射空间” 呢。
因此,Linux 规定“内核直接映射空间” 最多映射 896M 物理内存。
对于高端内存,可以通过 alloc_page() 或者其它函数获得对应的 page,但是要想访问实际物理内存,还得把 page 转为线性地址才行(为什么?想想 MMU 是如何访问物理内存的),也就是说,我们需要为高端内存对应的 page 找一个线性空间,这个过程称为高端内存映射。
高端内存映射有三种方式:
1、映射到“内核动态映射空间”
这种方式很简单,因为通过 vmalloc() ,在“内核动态映射空间”申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说高端内存有可能映射到“内核动态映射空间” 中。
2、永久内核映射
如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?
内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START ,用于映射高端内存。在 2.4 内核上,这个地址范围是 4G-8M 到 4G-4M 之间。这个空间起叫“内核永久映射空间”或者“永久内核映射空间”
通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。
通过 kmap(), 可以把一个 page 映射到这个空间来
3、临时映射
内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为“固定映射空间”
在这个空间中,有一部分用于高端内存的临时映射。
这块空间具有如下特点:
当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。
通过 kmap_atomic() 可实现临时映射。
下图简单简单表达如何对高端内存进行映射
篇3:操作系统内存管理
操作系统内存管理:总的来说,操作系统内存管理包括物理内存管理和虚拟内存管理。这里给大家分享一些关于操作系统内存管理,希望对大家能有所帮助。
计算机的存储体系
在介绍内存管理的细节前,先要了解一下分层存储器体系:
大部分的计算机都有一个存储器层次结构,即少量的非常快速、昂贵、易变的高速缓存(cache);若干兆字节的中等速度、中等价格、易变的主存储器(RAM);数百兆或数千兆的低速、廉价、不易变的磁盘。这些资源的合理使用与否直接关系着系统的效率。
CPU缓存(Cache Memory):是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多。缓存的出现主要是为了解决CPU运算速度与内存 读写速度不匹配的矛盾,因为CPU运算速度要比内存读写速度快很多,这样会使CPU花费很长时间等待数据到来或把数据写入内存。
计算机是一种数据处理设备,它由CPU和内存以及外部设备组成。CPU负责数据处理,内存负责存储,外部设备负责数据的输入和输出,它们之间通过总线连接在一起。CPU内部主要由控制器、运算器和寄存器组成。控制器负责指令的读取和调度,运算器负责指令的运算执行,寄存器负责数据的存储,它们之间通过CPU内的总线连接在一起。每个外部设备(例如:显示器、硬盘、键盘、鼠标、网卡等等)则是由外设控制器、I/O端口、和输入输出硬件组成。外设控制器负责设备的控制和操作,I/O端口负责数据的临时存储,输入输出硬件则负责具体的输入输出,它们间也通过外部设备内的总线连接在一起。
计算存储的层次结构
当前技术没有能够提供这样的存储器,因此大部分的计算机都有一个存储器层次结构:
高速缓存(cache): 少量的非常快速、昂贵、易变的高速缓存(cache);
主存储器(RAM): 若干兆字节的中等速度、中等价格、易变的主存储器(RAM);
磁盘: 数百兆或数千兆的低速、廉价、不易变的磁盘。
这些资源的合理使用与否直接关系着系统的效率。
物理内存:连续分配存储管理方式
连续分配是指为一个用户程序分配连续的内存空间。连续分配有单一连续存储管理和分区式储管理两种方式。
3.1 单一连续存储管理
在这种管理方式中,内存被分为两个区域:系统区和用户区。应用程序装入到用户区,可使用用户区全部空间。其特点是,最简单,适用于单用户、单任务的操作系统。CP/M和 DOS 2.0以下就是采用此种方式。这种方式的最大优点就是易于管理。但也存在着一些问题和不足之处,例如对要求内存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存。
3.2 分区式存储管理
为了支持多道程序系统和分时系统,支持多个程序并发执行,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。
分区式存储管理引人了两个新的问题:内碎片和外碎片。
内碎片是占用分区内未被利用的空间,外碎片是占用分区之间难以利用的空闲分区(通常是小空闲分区)。
为实现分区式存储管理,操作系统应维护的数据结构为分区表或分区链表。表中各表项一般包括每个分区的起始地址、大小及状态(是否已分配)。
分区式存储管理常采用的一项技术就是内存紧缩(compaction)。
篇4:DOS内存管理
在DOS下,系统中存在以下四种内存: 常规内存(ConventionalMemory); 高端内存(UpperMemory); 扩充内存(ExpandedMemory); 扩展内存(ExtendedMemory),
常规内存指的是0-640K的内存区。在DOS下,一般的应用程序只能使用系统的常规内存,因而都要受到640Kb内存的限制。而且由于DOS本身和config.sys文件中的安装的设备驱动程序和autoexec.bat文件中执行的内存驻留程序都要占用一些常规内存,所以应用程序能使用的常规内存是不到640K的。有很多时候,我们都要想方设法地整理内存,好为一些“胃口”比较大的应用程序留出足够的常规内存,这一点想必是许多DOS时代的电脑爱好者最熟悉不过的了。
高端内存是指位于常规内存之上的384K内存。程序一般不能使用这个内存区域,但是EMM386.exe可以激活高端内存的一部分,并且它允许用户将某些设备驱动程序和用户程序用Devicehigh或LH(即loadhigh)装入高端内存。dos=high,umb也是把DOS的一部分装到高端内存里,
这里的umb是高端内存块(UpperMemoryblock)的缩写。
扩充内存是一种早期的增加内存的标准,最多可扩充到32M。使用扩充内存必须在计算机中安装专门的扩充内存板,而且还要安装管理扩充内存板的管理程序。由于扩充内存是在扩展内存之前推出的,所以大多数程序都被设计成能使用扩充内存,而不能使用扩展内存。由于扩充内存使用起来比较麻烦,所以在扩展内存出现后不久就被淘汰了。
扩展内存只能用在80286或更高档次的机器上,目前几乎所有使用DOS的机器上超过1M的内存都是扩展内存。扩展内存同样不能被DOS直接使用,DOS5.0以后提供了Himem.sys这个扩展内存管理程序,我们可以通过它来管理扩展内存。emm386.exe可以把扩展内存(XMS)仿真成扩充内存(EMS),以满足一些要求使用扩充内存的程序。
最后再强调一下,不管扩充内存或扩展内存有多大,DOS的应用程序只能在常规内存下运行。有的程序可以通过DOS扩展器(比如DOS4GW.exe等程序)使CpU进入保护模式,从而直接访问扩展内存;但是要注意,进入保护模式以后,计算机就脱离了DOS状态。
篇5:glibc内存管理
X86平台LINUX进程内存布局如下:
上面个段的含义如下:
text:存放程序代码的,编译时确定,只读;
data:存放程序运行时就能确定的数据,可读可写;
bss:定义而没有初始化的全局变量和静态变量;
heap:一般由程序员分配,如果不释放的话在程序结束的时候可能被OS回收;
stack:有编译器自动分配释放,存放函数的参数、局部变量等;
Mmap:映射区域;
程序可以直接使用系统调用来管理heap和mmap,但更多的时候是使用C提供的malloc和free来动态地分配和释放内存,Linux上的stack的限制大致是8M,而在Windows上为2M.
C风格的内存管理程序:
也就是malloc和free,主要是通过brk或者mmap添加额外的虚拟内存。对于那些需要保持长期存储的程序使用malloc来管理内存可能会非常令人失望,如果有大量的不固定的内存引用,经常难以知道他们如何被释放。
池式内存管理:
应用程序可以更简单地管理内存;内存分配和回收更快;可以预先分配错误处理池,以便程序在常规内存被耗尽时仍然可以恢复;有非常易于使用的标准实现。
内存池只适用于操作可以分阶段的程序;通常不能和第三方库很好滴合作;如果程序的结构发生变化则不得不修改内存池;必须记住需要从哪个池进行分配。
引用计数:
不能忘记调用引用计数函数;无法释放作为循环数据结构的一部分;在多线程环境中更难也更慢。
垃圾回收:
永远不必担心内存的双重释放或者对象的生命周期;
无法干涉何时释放内存;比其他形式的内才能管理更慢;如果忘记将不再使用的指针设置为null,
内存管理器的设计目标:
最大化兼容性;
最大化可移植性(能很好地和OS交流);
浪费最小的空间(管理自身的数据结构也是需要内存的,还有一个需要注意的是碎片);
最快的速度(2/8原则,主要用来优化热点);
最大化可调性(能适应多种分配的需求,或者是通过配置来适应);
最大化局部性(这里考虑的是CPU的cache和内存之间的关系);
最大化调试功能(作为程序员就不用说了);
最大化适应性(在不修改配置时候的适应性);
ptmalloc实现了malloc和free以及一组其他函数,以提供动态内存管理的支持。分配器处于用户程序和内核之间,用来响应用户的分配请求,向操作系统申请内存,然后将其返回给用户程序。为了保持高效的分配,分配器一般都会预先分配一大块内存,并通过某种算法管理。用户释放掉的内存也并不是立即就返回给操作系统。ptmalloc在设计的时候折中了高效性、高空间利用率、高可用性等设计目标。其设计假设如下:
用mmap来分配长生命周期的大内存;
特别大的内存分配总是使用mmap;
短生命周期的内存分配使用brk;
尽量只缓存小的、临时使用的内存,而大的内存则直接归还给系统;
小内存块只有在malloc和free的时候进行合并;
收缩堆的条件是当前free的快的大小加上前后能合并的chunk的大小大于64K,并且堆顶的大小达到阀值;
需要长期存储的程序不适合ptmalloc;
总体上的结构如下:
而实际存在数据的是Chunk,使用中的Chunk的结构如下:
其中:
P:表示前一个Chunk是否在使用中;
M:标志Chunk是从那个内存区域获得的虚拟内存;
A:标志是否是主分配区;
空闲的Chunk在内存中的结构如下:
在glibc中使用bin来管理空闲的chunk,细节就不说了,
当空闲的chunk被链接到bin中的时候,ptmalloc会检查他前后的chunk是否也是空闲的,如果是的话,就会合并成一个大的chunk.bin的结构如下:
ptmalloc为了提高分配的速度,会把一些小的chunk先放到Fast bins中。fast bins中的chunk并不改变它的使用标志P,这样也就无法将他们合并,当用户分配小的内存的时候,ptmalloc首先会在fast bins中查找响应的空闲块,然后再去查找Unsorted bins中空闲的chunk.被合并后的chunk、或者是不能放在fast bins中的chunk会首先放在Unsorted bin中,如果在分配的时候在Unsorted bin中无法满足要求,则将Unsorted bin中的chunk加入到bins中。
因为在分配内存的时候是用低地址到高地址分配的,这样一个分配到的大的内存(用来模拟sub-heap)的上面很有可能是有一块空闲的内存,也就是Top chunk.Top chunk是在fast bin和bins之后才考虑的,所以这段区间并不在bins这些结构中。如果ptmalloc设法在top chunk中分配一段空间时且top chunk不够大,这时会重新分配一个新的sub-heap,并将top chunk迁移到新的sub-heap上。新的sub-heap与已有的sub-heap用单向链表连接起来。如下:
当要分配的空间足够大的时候,ptmalloc会使用mmap来直接使用内存映射来讲页映射到进程空间。这样分配的chunk在被free时将直接接触映射,再次对这样的内存区域的引用将会引起段错误。
Last remainder chunk是另外一种特殊的chunk,在分配一个small chunk的时候,如果在small bins中找不到合适的chunk,如果last remainder chunk的大小大于所需的small chunk大小。那么它将会分裂成两个,一个供用户使用,另一个变成了新的Last remainder chunk.
ptmalloc的响应用户内存分配请求的具体步骤:
获取主分配区的锁,如果失败就查找非主分配区,再不行就创建新的非主分配区;
将用户请求的大小转换为实际需要分配的chunk空间的大小;
如果chunk_size<=max_fast则转4,否则,跳转5;
尝试在fast bins中分配,如果成功则结束返回;
如果chunk_size<=512B则下一步,否则跳转6;
查找对应的small bins,如果找到则分配成功;否则转7;
合并fast bins中的chunk,遍历unsorted bin中的chunk,如果只有一个chunk,并且这个chunk在上次的分配中被使用过,并且所需分配的chunk大小属于smallbins,并且chunk的大小满足要求,则直接将该chunk进行切割,分配结束;否则将其放入bins;
在large bins中查找;如果失败转9;
如果top chunk满足要求,则从中分配出一块;否则转10;
如果是主分配区,调用sbrk增加top chunk的大小;否则分配一个新的sub-heap;或者直接使用mmap来分配;如果需要用mmap分配转11,否则转12;
使用mmap系统调用为程序的内存空间映射一块空间,然后将指针返回给用户程序;
判断是否第一次调用malloc,若是主分配区,则进行一次初始化工作。否则根据10的规则来分配。
为了避免Glibc内存暴增,使用时需要注意一下几点:
后分配的内存先释放(top chunk的考虑);
不适合用于管理长生命周期的内存,特别是持续不定期分配和释放长生命周期的内存;
不要关闭ptmalloc的mmap分配阀值动态调整机制;
多线程分阶段执行的程序不适合使用ptmalloc(更适合使用内存池);
尽量减少程序的线程数量和避免频繁分配、释放内存;
篇6:电脑内存选购方式
在当前网络技术管理中,计算机网络的运用,在提高网络技术管理效率的同时,还能进一步推动网络技术的发展。这里给大家分享一些关于电脑内存选购方式,希望对大家能有所帮助。
选购内存需要注意的地方
1.平台是否支持该内存
目前桌面平台所采用的内存主要为DDR 1、DDR 2和DDR 3三种,其中DDR1内存已经基本上被淘汰,而DDR2和DDR3内存是目前的主流产品。
三代内存之间的区别
由于三种类型的DDR内存之间,从内存控制器到内存插槽都互不兼容。而且即使是一些在同时支持两种类型内存的Combo主板上,两种规格的内存也不能同时工作,只能使用其中一种内存,所以大家在购买内存之前,首先要确定好自己的主板支持的内存类型。笔者就曾经碰到过有位朋友买了条DDR3内存回去插不进去主板,后面一看才发现主板是仅支持DDR2内存的P43......。
2.选择合适的内存容量和频率
内存的容量不但是影响内存价格的因素,同时也是影响到整机系统性能的因素。过去Windows XP平台,512M的内存还是主流,1GB已经是大容量;但是到了现在,64位系统开始普及,Windows 7越来越多人使用,没有2GB左右的内存都不一定能保证操作的流畅度。
Windows7系统对内存要求比XP高
但是,内存容量不见得是越大越好,大家在选购内存的时候也要根据自己的需求来选择,以达到发挥内存的最大价值。目前仍然使用32位XP系统的消费者,或者在长时间内不会升级至Vista或Windows7的朋友,2GB容量的内存是最佳的选择。
内存主频
和CPU一样,内存也有自己的工作频率,频率以MHz为单位。内存主频越高在一定程度上代表着内存所能达到的速度越快,内存主频决定着该内存最高能在什么样的频率正常工作,目前最为主流的内存频率为DDR2-800和DDR3-1333。
2选购内存需要注意的地方
3.产品做工要精良
对于选择内存来说,最重要的是稳定性和性能,而内存的做工水平直接会影响到性能、稳定以及超频。
内存做工要精良
内存颗粒的好坏直接影响到内存的性能,可以说也是内存最重要的核心元件。所以大家在购买时,尽量选择大厂生产出来的内存颗粒,一般常见的内存颗粒厂商有三星、现代、镁光、南亚、茂矽等,它们都是经过完整的生产工序,因此在品质上都更有保障。而采用这些顶级大厂内存颗粒的内存条品质性能,必然会比其他杂牌内存颗粒的产品要高出许多。
PCB电路板
内存PCB电路板的作用是连接内存芯片引脚与主板信号线,因此其做工好坏直接关系着系统稳定性。目前主流内存PCB电路板层数一般是6层,这类电路板具有良好的电气性能,可以有效屏蔽信号干扰。而更优秀的高规格内存往往配备了8层PCB电路板,以起到更好的效能。
金手指做工
内存“金手指”的优劣也直接影响着内存的兼容性甚至是稳定性,以通常采用的化学镀金工艺,一般金层厚度在3~5微米,而优质内存的金层厚度可以达到6~10微米。较厚的金层不易磨损,并且可以提高触点的抗氧化能力,使用寿命更长。
注意,这里一般所说的金手指“镀金”,并不是真的镀上“黄金”,而是镀“金属”,所以大家在卖场对于JS的内存“镀金”的说法也不必过于惊奇。
4.不能遗忘的SPD隐藏信息
SPD信息可以说非常重要,它能够直观反映出内存的性能及体制。它里面存放着内存可以稳定工作的指标信息以及产品的生产,厂家等信息。不过,由于每个厂商都能对SPD进行随意修改,因此很多杂牌内存厂商会将SPD参数进行修改或者直接COPY名牌产品的SPD,但是一旦上机用软件检测就会原形毕露。
Everest软件检测内存SPD信息
因此,大家在购买内存以后,回去用常用的Everest、CPU-Z等软件一查即可明白。不过需要注意的是,对于大品牌内存来说SPD参数是非常重要的,但是对于杂牌内存来说,SPD的信息并不值得完全相信。
5.小心假冒或返修产品
目前有一些内存往往使用了不同品牌、型号的内存颗粒,大家一眼就可以看出区别。同时有些无孔不入的JS也会采用打磨内存颗粒的作假手段,然后再加印上新的编号参数。不过仔细观察,就会发现打磨过后的芯片比较暗淡无光,有起毛的感觉,而且加印上的字迹模糊不清晰。这些一般都是假冒的内存产品,需要注意。
打磨的非常模糊的内存颗粒编号
此外,大家还要观察PCB电路板是否整洁,有无毛刺等等,金手指是否很明显有经过插拔所留下的痕迹,如果有,则很有可能是返修内存产品当然也不排除有厂家出厂前经过测试,不过比较少数。需要提醒大家的是,返修和假冒内存无论多么便宜都不值得购买,因为其安全隐患十分严重。
总结
通过本文简单的介绍之后,相信大家对选购内存有了一定的了解。在内存的选择上,笔者建议还是优先选购知名大厂的内存产品,虽然价格上会稍稍贵一点,但是主流品牌不仅品质有保证,而且一般都提供有“终身保修”的售后服务,最后希望大家都能够挑选出适合自己的优秀内存。
★ 数学教案-映射
★ 操作系统实习报告
★ 唯品会商业计划书
【Linux内存管理:高端内存的映射方式(共6篇)】相关文章:
单总线协议转换器在分布式测控系统中的应用2022-11-17
硬盘结构及硬盘错误的解决方法2022-04-29
Windows 服务器入侵前兆检测方法技巧服务器教程2023-09-19
暑期关于学习java实习报告2023-01-16
市场报告2022-06-20
windows服务器防止asp木马详细教程Windows服务器操作系统2022-04-30
的艺术类专业全面解析攻略2022-05-07
Windows系统安全设置方法中级安全篇服务器教程2023-03-02
计算机社会实践报告2023-06-10
蓝屏代码0x000000d1是什么意思?2023-06-04