这篇文章是本人的操作系统学习笔记系列二,接下来一周都会每天一更,欢迎阅读关注点赞!
命令:free -m
命令以MB为单位显示内存使用情况。
total
:总计物理内存的大小。
used
:已使用多大。
free
:可用有多少。
Shared
:多个进程共享的内存总额。
Buffers/cached
:磁盘缓存的大小。(buffer 是缓冲区,cache是页高速缓存。无论是缓冲区还是页高速缓存,它们的实现方式都是一样的。缓冲区只不过是一种概念上比较特殊的页高速缓存罢了)
available
还可以被 应用程序使用的物理内存大小
SWAP
是交换分区,也就是我们通常所说的虚拟内存(当我们内存不够用的时候就会用到这个SWAP),而当系统需要访问 swap 上存储的内容时,再将 swap 上的数据加载到内存中,这就是常说的换出和换入
free 与 available 的区别
https://blog.csdn.net/gpcsy/article/details/84951675或者https://www.cnblogs.com/sparkdev/p/7994666.html 可参考这篇文章
free
是真正尚未被使用的物理内存数量。
available
是应用程序认为可用内存数量,available = free + buffer + cache
(注:只是大概的计算方法)
Linux 为了提升读写性能,会消耗一部分内存资源缓存磁盘数据,对于内核来说,buffer 和 cache 其实都属于已经被使用的内存。但当应用程序申请内存时,如果 free 内存不够,内核就会回收 buffer 和 cache 的内存来满足应用程序的请求。这就是稍后要说明的 buffer 和 cache。
静态重定位是在程序执行之前进行重定位,它根据装配模块将要装入的内存起始位置,直接修改装配模块中的有关使用地址的指令。
静态重定位有着无需硬件支持的优点,但存在着如下的缺点:一是程序重定位之后就不能在内存中搬动了;二是要求程序的存储空间是连续的,不能把程序放在若干个不连续的区域内。
动态重定位是指,不是在程序执行之前而是在程序执行过程中进行地址重定位。更确切地说,是在CPU每次访问内存单元前才进行地址变换。
优点:
**缺点:**需要硬件支持。
物理内存分为固定大小的块,称为帧。
逻辑内存也分为同样大小的块,称为页。分页支持一直都是由硬件来处理的。
内存扩充
https://www.zhihu.com/question/21088377 参考博文
交换技术
有两种处理内存超载的通用方法:交换和虚拟内存
交换,就是当一个程序运行完,就立刻从内存中换出到磁盘,然后要用的时候再换入到内存,这里面的换入,会用到基址寄存器和界限寄存器来给程序进行动态重定位
交换的时候会产生多个空闲区,我们把这些小的空闲区合成一大块,这个技术就叫内存紧缩(通常是不进行这个操作,因为会耗费大量CPU时间)
虚拟内存,在上面那篇参考博文已经解释得非常清楚了,我就不重复了!
内碎片
内存固定分区的时候,出现分配的分区大于所需要的内存空间
外碎片
动态分区,内存中存在很多很小的空闲快,他们每一个都很小,不足以满足分配要求,但其综合满足分配要求。
无存储器抽象
一种存储器抽象:地址空间
主要功能:为了避免用户直接操作物理地址。为程序创造了一种抽象的内存
基址寄存器与界限寄存器
这两个寄存器就是为了解决上面那个困难的,这个方法就是动态重定位(简单地把每个进程的地址空间映射到物理内存的不同部分),也就是说使用动态重定位,每个进程的地址空间是可以重复的
缺点:每次访问内存都要进行运算,导致访问时间变长
存储管理的主要任务
内存分配和回收:由操作系统完成主存储器空间的分配和管理,使程序员摆脱存储分配的麻烦,提高编程效率。
地址变换:在多道程序环境下,程序中的逻辑地址与内存中的物理地址不可能一致,因此存储管理必须提供地址变换功能,把逻辑地址转换成相应的物理地址。
内存信息的共享和保护
上下界保护法
分区式存储管理,他也是一种连续内存分配方式,把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。
单一连续存储管理,内存被分为两个区域:系统区和用户区。其特点是,最简单,适用于单用户、单任务的操作系统。这种方式的最大优点就是易于管理。但也存在着一些问题和不足之处,例如对要求内存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存。只支持单道程序设计
**固定分区 **,将内存划分成若干个固定大小的块,分区大小可以相等也可不相等(划分之后不再改变)。
优点:易于实现,开销小。
缺点:主要有两个,内碎片造成浪费;分区总数固定,限制了并发执行的程序数目。
可变分区,动态分区的特点是动态创建分区:在装入程序时按其初始要求分配,或在其执行过程中通过系统调用进行分配或改变分区大小。其优点是:没有内碎片
但它却引入了另一种碎片—>外碎片。
系统要使用什么样的数据结构来记录内存的使用情况
空闲分区链(表)(大小 ,起址,状态)。
动态分区分配的实现:一个空闲表或者空闲链来记录目前系统中空间的内存区域。在内存分配时,需要查找空闲表或空闲链找到一块内存分配给当前进程。
空闲分区表
空闲分区链
使用位图
内存的大小和分配单元的大小决定了位图的大小,所以它提供了一种简单的利用一块固定大小的内存区就能对内存的使用情况进行记录,缺点就是,找出k个连续0的串是耗时的操作
分配算法
可变分区内存回收(使用链表管理)
合并相邻空闲区
假设,A地址是低地址,阴影部分是空闲区
Linux采用伙伴系统解决外部碎片的问题,监视内存,保证在内核只要申请一小块内存的情况下,不会从大块的连续空闲内存中截取一段过来,从而保证了大块内存的连续性和完整性。
伙伴系统的宗旨就是用最小的内存块来满足内核的对于内存的请求。
A先请求100KB,然后在1M中分成了两个512KB的内存块,一个分配给应用,一个是空闲,然后在分配给应用的512KB再分一半,分成了两个256KB,也是一样,一个分配给应用,一个是空闲,发现还可以再分,就把256kb一样分两份,最后发现不能分了,就不分了。页框块在释放时,会主动将两个连续的页框块合并成一个较大的页框块。
伙伴系统的一个优点是:通过称为合并的技术,可以将相邻伙伴快速组合以形成更大分段。
伙伴系统的明显缺点是:
每个 slab 由一个或多个物理连续的页面组成,每个 cache 由一个或多个 slab 组成,每个内核数据结构都有一个 cache。slab 分配算法采用 cache 来存储内核对象。
lab 分配器提供两个主要优点:
https://zhuanlan.zhihu.com/p/37549063 这里推荐这篇文章
CPU生成的每个地址分为两个部分:页号和页偏移。页号作为页表的索引。页表包含每页所在物理内存的基地址。
逻辑地址到物理地址的变换过程
以上可能会是一道大题,记住公式:
页号 P=逻辑地址/页大小
页内地址 F=逻辑地址%页大小
物理地址 A=物理块号*页大小 + 页内地址
页表/快表(TLB,Translation Look aside Buffer),
一道关于块表的题目
一级页表的缺陷,由于页表必须连续存放,并且需要常驻物理内存,当逻辑地址空间很大时,导致页表占用内存空间很大。采用离散分配方式的管理页表,将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。(按需调入)
二级页表,二级页表即是对页表本身采用分页式管理,对页表本身增加了一层页表管理。(其实这种管理方式是很通用的,后面学到的文件系统,inode结点也可以像这样存储)
多级页表,多级页表和二级页表是为了节省物理内存空间。使得页表可以在内存中离散存储。(单级页表为了随机访问必须连续存储,如果虚拟内存空间很大,就需要很多页表项,就需要很大的连续内存空间,但是多级页表不需要。)
缺页中断,当软件试图访问已映射在虚拟地址空间中,但是目前并未被加载在物理内存中的一个分页时,由中央处理器的内存管理单元所发出的中断。 https://www.cnblogs.com/sunsky303/p/9214223.html 参考博文
页面置换算法,进程运行过程中,如果发生缺页中断,而此时内存中有没有空闲的物理块是,为了能够把所缺的页面装入内存,系统必须从内存中选择一页调出到磁盘的对换区。
最佳置换(OPT),淘汰将来不再使用或者在最远的将来才可能被使用的页。但是该算法需要依据以后各业的使用情况,而当一个进程还未运行完成,很难估计哪一个页面是以后不再使用或在最长时间以后才会用到的页面。所以该算法是不能实现的。它可作为衡量其它算法优劣的一个标准
举个例子:
访问到3的时候,比较内存里面的0,2,3哪一个最近不会被使用,看了后面的访问顺序,发现是5不再使用了,所以就淘汰5,以此类推
先进先出淘汰算法(FIFO),淘汰最先调入内存的页
最近最少使用淘汰算法(LRU),淘汰最近最久没有被使用的页。LRU算法普偏地适用于各种类型的程序,但是系统要时时刻刻对各页的访问历史情况加以记录和更新,开销太大,因此LRU算法必须要有硬件的支持。系统使用特殊的堆栈来存放内存中每一个页面的页号。每当访问一页时就调整一次,即把被访问页面的页号从栈中移出再压入栈顶。因此,栈顶始终是最新被访问页面的页号,栈底始终是最近最久未被访问的页号。当发生缺页中断时,总是淘汰栈底页号所对应的页面。
**抖动现象:**刚被淘汰的页,又要被访问,频繁发生。
工作集:是指进程在某个时间段里要访问的页的集合。思路:页置换的时候,锁住缺页的进程,不让其缓冲。而调入的页占据那些暂时得不到执行的进程所占据的内存区域。
https://www.cnblogs.com/wkfvawl/p/11733057.html 这里推荐一篇文章
参考资料:
好了,又到了个人唠叨时间,这次该说点什么好呢?嗯,我觉得说说考研这件事吧,因为前段时间有些朋友来问过我关于考研的事情,因为之前我是决定好要考研的,但是,现在又不想考了,所以现在就聊聊考研这件事!
我为什么会放弃考研
其实,网上有很多文章都是说考研和工作的,大家可以去看看,毕竟现在的我还没有一点成就,很难写出一些让人信服的故事,所以今天就以一种轻松愉快的心态聊聊考研这件事!相信很多朋友从进大学的那一刻都是很迷茫的,到底大学的意义是什么?我为什么要上大学呢?
我的理解是,大学就是一个平台,是一个从学生时代过渡到社会的平台,大学是一个可以勇敢试错的平台,所以,你在这里犯下的所有错误,付出的代价都是极小的,所以,我们在大学期间,千万不要怕试错,每一条路都可以尝试去走走,如果最后也没有找到自己想走的那条路也没关系,只要你还在大学,就能一直试错!所以,我在这里是鼓励大家多学习,找到自己喜欢的东西,不管是不是专业对口,只要你喜欢就行,比如你很喜欢打篮球,觉得以后可以走篮球这条路,你就要好好走下去,不要半途而废。但是,现实是很残酷的,所以,我并没有选择自己喜欢的东西,这里就谈到为什么我会选择这个专业,其实就是因为看到了一个年度工资表,看到软件工程这个专业的工资非常高,所以就选择了这个专业。很庆幸,我也慢慢喜欢上了这个专业。
好像越扯越远了,再来说说为什么我会放弃考研,上篇文章说到我的高考失利,这里说说我当初不去复读的原因吧,我觉得人生不应该要走回头路,复读是对自己过去的不认可(嗯,这只是个人看法,不喜勿喷),所以,我想通过考研来改变自己的学历,向上一个好的大学,想试试上好大学的滋味,**还有一个原因是当初想考研就是为了想炫耀自己,因为身边的朋友都上了重本了,我就想炫耀回去,就是想满足自己的虚荣心。**所以,大一这一年,我是非常看重这个绩点和基础的,无论是什么课都不敢逃,凡是要考试的课都会尽心尽力学一下。结果,大一绩点果然上来了,也拿到了奖学金!
到这里,要开始说重点了,我其实是在这学期才决定放弃考研的,一个原因就是:考研真的不适合我,为什么会这么说呢?我在寒假的时候也学过一段时间的考研数学和英语,发现自己真的没有数学和英语的天赋,数学听不懂,英语背不会!!可能这是一种懦弱的表现吧,人总是想逃离自己的恐慌区,所以,一个人想增长自己的优点很容易,要补一下自己的缺点却怎么补都补不了!另一个原因就是:我找到了我想要的东西,考研并不能直接帮到我!当初考研是为了什么,为了炫耀,为了提高学历,仅此而已!! 那其实抛开这个炫耀,那提高学历的目标是什么呢?最后也是为了找工作,既然最终目标都是想找一个好工作,那为什么我本科不拼一把,找到一份好的工作,而是要上研究生呢?所以,我决定从现在开始就拼一把!
说了这么多,最重要的还是自己要明确目标啊!还有一个是方向问题,有朋友也问过,这里稍微提一下吧,其实为什么我最后会选择java方向,其实这跟学习的东西是有关的,当你真正去接触一个方向的时候,我学到的东西越来越多,给自己的正反馈越来越多,你就会越来越喜欢这个方向!所以,简单来说就是先做后想,先去做了再去想这个方向合不合适自己!因为很多东西都是,你厉害了,你收到的正反馈多了,你才会慢慢喜欢上这个多西!
好了,今天就说这么多吧!有什么问题欢迎和我探讨!
*,那为什么我本科不拼一把,找到一份好的工作,而是要上研究生呢?所以,我决定从现在开始就拼一把!
说了这么多,最重要的还是自己要明确目标啊!还有一个是方向问题,有朋友也问过,这里稍微提一下吧,其实为什么我最后会选择java方向,其实这跟学习的东西是有关的,当你真正去接触一个方向的时候,我学到的东西越来越多,给自己的正反馈越来越多,你就会越来越喜欢这个方向!所以,简单来说就是先做后想,先去做了再去想这个方向合不合适自己!因为很多东西都是,你厉害了,你收到的正反馈多了,你才会慢慢喜欢上这个多西!
好了,今天就说这么多吧!有什么问题欢迎和我探讨!