win服务器 内存释放 在校招中顺利拿到更好的offer,你准备好了吗?

操作系统

如果你想在校招过程中顺利拿到更好的offer,阿秀推荐你看看前辈的经验,比如准备、简历、实习、落地经验、校招总结、阿里、字节、腾讯、美团等一二线厂商等;如果你是电脑新手,在升学/转学/校招的路上迷茫或需要帮助,可以;免费分享阿秀自学个人电脑以来收集到的好资源。 , 点击这里;如果需要网站“阿秀学习笔记”的求职知识点PDF版,可以

41、Windows 和 Linux 环境中的内存分布

图片[1]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

从这张图可以看出,用户空间内存,从低到高,是7个不同的内存段:

42、C/C++编译的程序占用了哪些内存?

1、栈区(stack)——地址向下增长,由编译器自动分配和释放,存放函数的参数值、局部变量的值等。它的操作类似于数据结构中的栈,先进后出。

2、堆区(heap)——地址向上增长,一般由程序员分配和释放。如果程序员不释放它,它可能会在程序结束时被操作系统回收。注意与数据结构中的堆不同,分配方式与链表类似。

3、全局区(静态区)(静态)——全局变量和静态变量的存储放在一起,初始化的全局变量和静态变量在同一个区域,未初始化的全局变量和未初始化的变量静态变量位于另一个相邻区域。 – 程序结束后有系统发布

4、Literal Constants Area – 这是放置常量字符串的地方。程序结束后由系统释放

5、程序代码区(文本)——存储函数体的二进制代码。

43、Linux/windows平台下一般栈空间大小

操作系统决定Linux环境,一般8MB,8192KB,可以通过ulimit命令查看修改

由Windows环境下的编译器决定,VC++6.0一般为1M

Linux

在linux下,栈大小不是由编译器决定的,而是由操作系统环境决定的。默认为 8192KB(8M);而在 Windows 平台下,堆栈的大小记录在可执行文件中(由编译器设置)。 )win服务器 内存释放,即:在Windows下,栈大小由编译器决定,而在Linux下,栈大小由系统环境变量控制。

在Linux下可以通过以下命令查看和设置堆栈大小:

$ ulimit -a            # 显示当前栈的大小 (ulimit为系统命令,非编译器命令)       
$ ulimit -s 32768      # 设置当前栈的大小为32M

1

2

窗户

程序栈空间大小,VC++ 6.0 默认栈空间为1M。

如何在VC中修改栈大小6.0:

感谢网友的勘误:已更正! -2021.09.03

44、程序从堆中动态分配内存时,虚拟内存是如何操作的

页表:是存储在物理内存中的数据结构,记录了虚拟页和物理页的映射关系

在动态内存分配过程中,如malloc()函数或其他高级语言中的new关键字,操作系统会在硬盘上创建或申请一个虚拟内存空间并更新到页表(分配页表项)(PTE),使PTE指向硬盘上新创建的虚拟页),通过PTE建立虚拟页与物理页的映射关系。

45、几种常见的磁盘调度算法

影响磁盘块读写时间的因素有:

其中寻道时间最长,所以磁盘调度的主要目标是尽量减少磁盘的平均寻道时间。

1.先到先得

按照磁盘请求的顺序安排。

优点是公平和简单。缺点也很明显,因为没有对seek进行优化,所以平均seek时间会比较长。

2. 最短寻道时间优先

最好调度离当前磁头所在轨道最近的轨道。

虽然平均寻道时间很短,但这并不公平。如果新到达的轨道请求总是比等待的轨道请求更近,那么等待的轨道请求将永远等待,即饥饿。具体来说,两端的跟踪请求更容易出现饥饿。

图片[2]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

3.电梯扫描算法

电梯一直保持在一个方向运行,直到该方向没有请求,然后改变运行方向。

电梯算法(扫描算法)类似于电梯的运行过程。磁盘调度总是在一个方向上执行,直到该方向上没有未完成的磁盘请求,然后再改变方向。

因为考虑了运动的方向,所以所有的磁盘请求都会得到满足,解决了SSTF的饥饿问题。

图片[3]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

46、交换空间与虚拟内存交换空间的关系

Linux 中的交换空间在物理内存 (RAM) 已满时使用。如果系统需要更多内存资源并且物理内存已满,则将内存中的非活动页面移动到交换空间。虽然交换空间对内存量较小的机器有帮助,但这种方法不应被视为内存的替代品。交换空间位于硬盘驱动器上,它比进入物理内存要慢。交换空间可以是专用交换分区(推荐方法)、交换文件或两者的组合。交换空间的总大小应等于计算机内存的两倍或 32 MB,以较大者为准,但不能超过 2048MB (2 GB)。

虚拟内存

虚拟内存是与文件数据交叉链接的活动文件。它是 WINDOWS 目录中的“WIN386.SWP”文件。该文件将继续自动扩展和收缩。在速度方面,CPU 的 L1 和 L2 缓存是最快的,其次是内存和硬盘。但是虚拟内存使用的是硬盘空间,为什么我们要用最慢的硬盘作为虚拟内存呢?因为计算机中运行的所有程序都需要通过内存来执行,如果执行的程序很大或者很多,就会导致我们只有可怜的256M/512M内存耗尽。硬盘空间往往是几十G到几百G。为了解决这个问题,Windows采用了虚拟内存技术,即将硬盘空间的一部分用作内存。

47、你知道什么是抖动吗?也叫颠簸现象

刚刚换出的页面会再次换入内存,刚刚换入的页面会立即换出外部内存。这种频繁的寻呼行为称为抖动或抖动。出现抖动的主要原因是进程频繁访问的页数高于可用物理块数(分配给进程的物理块不够)

为进程分配太少的物理块可能会导致进程崩溃。为一个进程分配了过多的物理块,会降低系统的整体并发性,降低某些资源的利用率。为了研究应该为每个进程分配多少物理块,Denning 提出了“进程工作集”的概念 p>

48、从堆和栈创建对象哪个更快? (查看堆和栈的分配效率对比)

从两个方面考虑:

49、常见的内存分配方式有哪些?

内存分配方式

(1)从静态存储区分配。内存是在程序编译的时候分配的,这个内存在程序的整个运行期间都存在。比如全局变量,静态变量。

(2)是在栈上创建的。函数执行时,可以在栈上创建函数中局部变量的存储单元,这些存储单元会在函数执行结束时自动释放.栈内存分配操作内置处理器的指令集效率很高,但分配的内存容量有限。

(3)从堆中分配,也称为动态内存分配。程序运行时,使用malloc或new申请任意数量的内存,由程序员负责何时使用free或删除释放内存。动态内存的生命周期由我们自己决定,使用起来很灵活,但问题也最多。

50、常见的内存分配内存错误

(1)内存分配不成功,但是被使用了。

新程序员经常犯这个错误,因为他们没有意识到内存分配会失败。一个常见的解决方案是在使用内存之前检查指针是否为 NULL。如果指针 p 是函数的参数,则在函数入口处使用 assert(p!=NULL) 对其进行检查。如果使用 malloc 或 new 分配内存,则应使用 if(p==NULL) 或 if(p!=NULL) 进行防错。

(2)虽然内存分配成功,但是在初始化之前就被引用了。

犯这个错误主要有两个原因:一是没有初始化的概念;另一种是内存默认初始值全为零,导致引用的初始值错误(比如数组)。内存的默认初始值是多少没有统一的标准,尽管有时它是零,我们宁愿相信它。所以不管用什么方法创建数组,别忘了赋初值,即使赋零也不能省略,不要太麻烦。

(3)内存分配成功并初始化,但操作越过了内存边界。

例如,下标“more 1”或“less 1”的操作在使用数组时经常会出现。尤其是在for循环语句中,很容易在循环次数上出错,导致越界数组操作。

(4)忘记释放内存,导致内存泄漏。

每次调用出现此错误的函数都会丢失一大块内存。起初系统有足够的内存,你看不到错误。有一次程序突然挂掉,系统提示:内存耗尽。动态内存的申请和释放必须成对,并且程序中malloc和free的使用次数必须相同,否则一定会报错(类似于new/delete)。

(5)释放内存但继续使用。常见的三种情况:

51、在内存交换中,被换出的进程存放在哪里?

保存在磁盘上,即外部存储器中。在具有交换功能的操作系统中,磁盘空间通常分为两部分:文件区和交换区。文件区主要用于存储文件,主要追求存储空间的利用率。因此,文件区空间的管理采用离散分配;交换区只占磁盘空间的一小部分,交换后的进程数据存放在文件区。改变区域。由于交换的速度直接影响系统的整体速度,所以交换区的管理主要追求换入换出的速度。因此,交换区通常是连续分配的(学习文件管理章节后就可以理解了)。简而言之,交换区的 I/O 速度比文件区快。

52、发生内存交换时哪些进程优先?你能说点什么吗?

阻塞进程可以先换出;可以换出低优先级的进程;为了防止低优先级的进程在转移到内存后很快被换出,有些系统还会考虑该进程在内存中的常驻进程。保持时间…(注意:PCB会留在内存中,不会被换出外部内存)

53、ASCII、Unicode、UTF-8编码有什么区别? ASCII

ASCII只有127个字符,代表英文字母、数字和一些符号的大小写,但是因为其他语言使用ASCII编码来表示字节不足,例如:常用中文需要两个字节,而不能与ASCII冲突,中国GB2312编码格式已定制。同样,其他国家的语言也有自己的编码格式。

统一码

由于每个国家的语言都有自己的编码格式,多语言编辑文本中会出现乱码,于是Unicode应运而生。 Unicode就是把这些语言统一成一套编码格式,通常两个单词Section代表一个字符,而ASCII是一个字节代表一个字符,所以如果你编译的文本是全英文,使用Unicode编码需要两倍存储空间为ASCII编码,存储和传输非常不经济。

UTF-8

为了解决以上问题,将Unicode编码转换为“变长编码”UTF-8编码。 UTF-8编码根据数字大小将Unicode字符编码为1-6个字节,英文字母编码。成一个字节,普通汉字编码成三个字节,如果你编译的文本是纯英文,那么使用UTF-8会节省空间,ASCII码也是UTF-8的一部分。

三者之间的联系

在理清了ASCII、Unicode和UTF-8的关系之后,我们可以总结一下计算机系统中常用的字符编码的工作方法:

(1)在计算机内存中统一使用Unicode编码,当需要保存到硬盘或需要传输时,转为UTF-8编码。

(2)使用记事本编辑时,将从文件中读取的UTF-8字符转换为Unicode字符并存储在内存中。编辑后,保存时Unicode转换为UTF-8。到文件。如下图(别人的图片截图)

图片[4]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

在浏览网页时,服务器会将动态生成的 Unicode 内容转换为 UTF-8 传输给浏览器:

图片[5]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

54、原子操作是如何实现的

**处理器基于缓存锁或总线锁实现多个处理器之间的原子操作。 **首先,处理器自动保证基本内存操作的原子性。处理器保证从系统内存读取或写入一个字节是原子的,这意味着当一个处理器读取一个字节时,其他处理器无法访问该字节的内存地址。 Pentium 6 和最新的处理器可以自动保证单个处理器对同一缓存行的 16/32/64 位操作是原子性的,但是复杂的内存操作处理器不能自动保证其原子性,例如跨总线宽度、跨多个访问缓存行和跨页表。但是,处理器提供了两种机制,总线锁定和缓存锁定,以确保复杂内存操作的原子性。

(1)使用总线锁保证原子性第一种机制是通过总线锁保证原子性。如果多个处理器同时读写共享变量(i++是经典的读写操作),那么共享变量会被多个处理器同时操作,所以read-modify-write操作不是原子的,操作后共享变量的值会与期望值不一致,例如如果i=1,我们执行了两次 i++ 操作,我们期望结果为 3,但也有可能结果为 2,如下图所示。

CPU1    CPU2
 i=1     i=1
 i+1     i+1
 i=2     i=2

1

2

3

4

原因可能是多个处理器同时从各自的缓存中读取变量iwin服务器 内存释放,加1,然后分别写入系统内存。那么,为了保证读写共享变量的操作是原子的,必须保证CPU1读写共享变量时,CPU2不能操作缓存共享变量内存地址的cache。

处理器使用总线锁来解决这个问题。所谓总线锁就是利用处理器提供的LOCK#信号。当一个处理器在总线上输出这个信号时,其他处理器的请求就会被阻塞,这样处理器就可以独占共享内存。

(2)使用缓存锁保证原子性第二种机制是通过缓存锁保证原子性。同时我们只需要保证对某个内存地址的操作是原子的,但是总线锁锁住了CPU和内存的通信,使得其他处理器在锁期间无法操作其他内存地址的数据,所以总线锁的开销比较大,目前处理器使用的是缓存锁而不是总线锁定优化。

经常使用的内存缓存在处理器的L1、L2和L3缓存中,因此原子操作可以直接在处理器的内部缓存中执行,无需声明总线锁。在 Pentium 6 和当前的处理器中可以使用“缓存锁定”来实现复杂的原子性。

所谓“缓存锁”是指如果内存区域被缓存在处理器的缓存行中,并在Lock操作期间被锁定,那么当它执行锁定操作并写回内存时,处理器不会断言总线上的LOCK#信号而不是修改内部内存地址并允许其缓存一致性机制保证操作的原子性,因为缓存一致性机制防止同时修改两个以上处理器缓存的内存区域中的数据,当其他处理缓存时写回锁定的缓存行的数据,缓存行将失效。上图示例中,当CPU1修改cache line中的i时,使用了cache lock,那么CPU2就不能同时使用cache i了。缓存线。

有两种情况处理器不会使用缓存锁定。第一种情况是当被操作的数据不能缓存在处理器内部,或者被操作的数据跨越多个缓存行时,处理器调用总线锁定。第二种情况是:有些处理器不支持缓存锁定。对于 Intel 486 和 Pentium 处理器,即使锁定的内存区域位于处理器的高速缓存行中,也会调用总线锁定。

55、你知道内存交换有哪些要注意的重点吗? Swap 需要备份存储,通常是一个快速磁盘,它必须足够大并提供对这些内存映像的直接访问。为了高效地使用CPU,每个进程的执行时间需要比交换时间长,而影响交换时间的主要因素是传输时间,它与交换的空间内存成正比。例如,如果您换出一个进程,请确保该进程的内存空间是成比例的。交换空间通常作为单个磁盘块使用,独立于文件系统,因此可以快速使用。交换通常在有许多进程运行且内存空间紧张时启动,并在系统负载减少时暂停。普通交换使用的不多,但交换策略的一些变体仍然适用于许多系统(如 UNIX 系统)。 56、系统并发和并行,你分得清吗?

并发是指在一个宏观的时期内同时运行多个程序的能力,而并行性是指同时运行多条指令的能力。

并行性需要硬件支持,例如多管道、多核处理器或分布式计算系统。

操作系统通过引入进程和线程使程序能够并发运行。

57、可能是最全面的页面替换算法总结1、Optimal Replacement Method (OPT)

最优替换算法(OPT,Optimal):每次淘汰的页面都是以后永远不会使用的页面,或者最长时间不会被访问的页面,可以保证页面错误率最低.

图片[6]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

最优替换算法可以保证最低的缺页率,但实际上只有在进程执行过程中才能知道接下来会访问哪个页面。操作系统无法提前预测页面访问的顺序。因此,最优置换算法是无法实现的

2、先进先出置换算法(FIFO)

先进先出替换算法(FIFO):每次选择淘汰的页是第一个进入内存的页。实现方法:将加载到内存中的页面按照加载顺序排列成一个队列,需要换出页面。行头页队列的最大长度取决于系统为进程分配了多少内存块。

图片[7]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

图片[8]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

延迟异常 – 当分配给进程的物理块数量增加时,页面错误的数量增加而不是减少。

只有 FIFO 算法会产生 Belady 异常,而 LRU 和 OPT 算法不会产生 Belady 异常。另外,虽然FIFO算法实现简单,但该算法并不适应进程实际运行的规律,因为最先进入的页面也可能被最频繁地访问。因此,算法的性能较差

FIFO的性能较差,因为较早调入的页面往往是被频繁访问的页面,而这些页面在FIFO算法下被反复调入调出,存在Belady现象。所谓 Belady 现象是指:在使用 FIFO 算法时,如果一个进程没有分配它所需要的所有页,有时会出现分配页数增加但缺页率反而增加的异常现象。

3、最近使用的置换算法(LRU)

Last最近使用的替换算法(LRU,最近最少使用):每次淘汰的页面是最长时间没有被使用的页面。实现方法:在每个页面对应的页表条目中,使用访问字段记录该页面的 .自上次访问后经过的时间 t(该算法的实现需要特殊的硬件支持,虽然该算法性能不错,但实现难度大,开销大)。当需要淘汰某个页面时,选择现有页面中t值最大的页面,即最长时间未被使用的页面。

LRU 具有更好的性能,但需要对寄存器和堆栈的硬件支持。 LRU 是一种栈式算法。理论上可以证明栈式算法中不会发生Belady异常。

图片[9]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

如果手动做题时需要剔除页码,此时可以反查内存中的页码。反向扫描过程中出现的最后一个页码是要消除的页面。

4、时钟替换算法(CLOCK)

最优替换算法的OPT性能最好,但无法实现;先进先出置换算法实现简单,但算法性能较差;最长时间没有使用的替换算法性能不错,最接近OPT算法的性能,但是实现需要特殊的硬件支持,算法开销高。

因此操作系统的设计者尝试了许多算法,试图以相对较少的开销接近 LRU 的性能。这些算法都是CLOCK算法的变种,因为该算法需要循环扫描缓冲区并像时钟一样旋转。所以叫时钟算法。

时钟替换算法是一种性能和开销平衡的算法,也称为CLOCK算法,或最近未使用的算法(NRU,Not Recent Used)

简单的CLOCK算法实现方法:为每个页面设置一个访问位,然后通过链接指针将内存中的页面链接成一个循环队列。当一个页面被访问时,它的访问位置是1。当一个页面需要被淘汰时——只需检查该页面的访问位。如果为0,则选择要换出的页面;如果是1,则设置为0,暂时不要换出,继续检查下一页,如果- – ~轮扫描的所有页面都是1,则将页面的访问位设置为0依次进行第二轮扫描(第二轮扫描必须有访问位为0的页面,所以简单的CLOCK算法选择——被淘汰的页面最多经过两轮扫描)

图片[10]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

5、改进的时钟替换算法

一个简单的时钟替换算法只考虑最近是否访问过一个页面。实际上,如果退休页没有被修改,则无需执行 I/O 操作将其写回外部存储器。只有被淘汰的页面在被修改和废弃时才需要写回外部存储器。

因此,操作系统除了要考虑一个页面最近是否被访问过,还要考虑该页面是否被修改过。在其他条件相同的情况下,应先剔除未修改的页面,以避免进行 I/O 操作。这就是改进的时钟替换算法的思想。修改位=0,表示页面没有被修改;修改位=1,表示页面已被修改。

为了讨论方便,每个页面的状态都以(访问位,修改位)的形式表示。例如(1,1)表示一个页面最近被访问过并被修改过。

改进后的Clock算法需要综合考虑一个内存页的访问位和修改位来决定是否替换该页。在实际编写算法的过程中,也可以用一个等长的整数数组来标识每个内存块的修改状态。访问位A和修改位M可以构成以下四种页面。

算法规则:将所有可能被替换的页面排列成一个循环队列

第一轮:从当前位置扫描到第一帧(A=0,M=0))进行替换。表示该页面最近没有被访问或修改过,并且是最第二轮最佳淘汰页面:如果第一轮扫描失败,重新扫描找到第一个(A=1,M=0) frame 进行替换。本轮将访问所有扫描到的帧,将 bits 设置为 0。表示该页最近没有被访问过,而是被修改过,所以不是一个好的淘汰页。第三轮:如果是第二轮扫描失败,重新扫描找到第一个(A=0,M=1)的帧用于替换。本轮扫描不修改任何标志位,表示该页已被最近访问但没有被修改,可能会再次访问该页面第四轮:如果第三轮扫描失败,重新扫描找到第一帧A=1,M=1)进行替换. 表示该页面最近被访问和修改过,该页面可能会被再次访问。

由于第二轮已经将所有帧的访问位设置为0,所以在第三轮和第四轮扫描后必须选择一帧。因此,改进后的CLOCK替换算法选择——一个被淘汰的页面最多执行四轮扫描

图片[11]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

算法规则:将所有可能被替换的页面排列成一个循环队列。第一轮:从当前位置扫描到第一个(0,0)帧进行替换。本轮扫描不修改任何标志位。(第一优先级:最近未访问且未修改的页面) ) 第二轮:如果第一轮扫描失败,重新扫描找到第一个(0,1)帧)进行替换。这一轮将所有扫描的帧访问位设置为0(第二优先级:没有被访问过的页面最近,但已经修改) 第三轮:如果第二轮扫描失败,重新扫描找到第一轮扫描(0,0)帧用于替换。本轮扫描不修改任何标志位(第三优先:最近访问过但未修改的页面)第四轮:如果第三轮扫描失败,则重新扫描找到第一个(0,1)帧进行替换。(第四优先:最近访问和修改页)由于第二轮已经设置所有帧的访问位为0,所以经过t第三和第四轮扫描,必须选择一帧,所以改进的CLOCK替换算法选择一个被淘汰的页面,最多进行四轮扫描

6、总结算法规则的优缺点

选择

最好去掉最长时间不会访问的页面

缺页率最小,性能最好;但无法实现

先进先出

最好将第一页消除到内存中

实施简单;但性能不佳,可能会出现 Belady 异常

LRU

最好剔除最长时间未访问的页面

性能非常好;但需要硬件支持,算法开销大

时钟 (NRU)

Cycle scan each page The first round eliminates the access bit = 0, and changes the access bit of the scanned page to 1. If the first round is not selected, the second round of scanning is performed.

The implementation is simple and the algorithm overhead is small; but whether the page has been modified is not considered.

Improved CLOCK (Improved NRU)

If it is expressed in the form of (access bit, modification bit), then the first round: Eliminate (0, 0) The second round: Eliminate (O, 1), and the scanned page All access bits are set to 0 Third round: Elimination (O, 0) Fourth round: Elimination (0, 1)

The algorithm has less overhead and good performance

58、What is sharing?

Sharing means that resources in the system can be shared by multiple concurrent processes.

There are two types of sharing: mutually exclusive sharing and simultaneous sharing.

Resources that are mutually exclusive and shared are called critical resources, such as printers, etc., only one process is allowed to access at the same time, and a synchronization mechanism is required to achieve mutually exclusive access.

59、A summary of deadlock related issues, super complete!

Deadlock refers to the process in which two (multiple) threads wait for each other’s data. The occurrence of deadlock will cause the program to freeze, and the program will never be able to proceed without unlocking.

1、Deadlock causes

For example: two threads A and B, two data 1 and 2. During the execution of thread A, it first locks resource 1, and then locks resource 2. However, due to thread switching, thread A fails to lock resource 2. After the thread is switched to B, thread B first locks resource 2, and then locks resource 1. Since resource 1 has been locked by thread A, thread B cannot successfully lock. When thread is switched to A, A Resource 2 cannot be successfully locked, which causes both threads AB to wait for a locked resource, resulting in a deadlock.

Theoretically, there are four necessary conditions for deadlock to occur, and none of them are indispensable:

Mutual exclusion condition: The process has exclusive access to the required resource. If another process requests the resource, the requesting process can only wait.

No deprivation condition: The process cannot be forcibly taken away by other processes before the acquired resources are released, but can only be released by itself.

Request and hold conditions: The resources currently owned by the process will continue to be occupied by the process when the process requests other new resources.

Circular waiting condition: There is a circular waiting chain for process resources, and the resources obtained by each process in the chain are simultaneously requested by the next process in the chain.

2、Deadlock demo

The demonstration in the form of code requires two threads and two mutexes.

#include 
#include 
#include 
#include 
#include   //引入互斥量头文件
using namespace std;
class A {
public:
	//插入消息,模拟消息不断产生
	void insertMsg() {
		for (int i = 0; i < 100; i++) {
			cout << "插入一条消息:" << i << endl;
			my_mutex1.lock(); //语句1
			my_mutex2.lock(); //语句2
			Msg.push_back(i);
			my_mutex2.unlock();
			my_mutex1.unlock();
		}
	}
	//读取消息
	void readMsg() {
		int MsgCom;
		for (int i = 0; i < 100; i++) {
			MsgCom = MsgLULProc(i);
			if (MsgLULProc(MsgCom)) {
				//读出消息了
				cout << "消息已读出" << MsgCom << endl;
			}
			else {
				//消息暂时为空
				cout << "消息为空" << endl;
			}
		}
	}
	//加解锁代码
	bool MsgLULProc(int &command) {
		int curMsg;
		my_mutex2.lock();   //语句3
		my_mutex1.lock();   //语句4
		if (!Msg.empty()) {
			//读取消息,读完删除
			command = Msg.front();
			Msg.pop_front();
			
			my_mutex1.unlock();
			my_mutex2.unlock();
			return true;
		}
		my_mutex1.unlock();
		my_mutex2.unlock();
		return false;
	}
private:
	std::list Msg;  //消息变量
	std::mutex my_mutex1; //互斥量对象1
	std::mutex my_mutex2; //互斥量对象2
};
int main() {
	A a;
	//创建一个插入消息线程
	std::thread insertTd(&A::insertMsg, &a); //这里要传入引用保证是同一个对象
	//创建一个读取消息线程
	std::thread readTd(&A::readMsg, &a); //这里要传入引用保证是同一个对象
	insertTd.join();
	readTd.join();
	return 0;
}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

Statements 1 and 2 indicate that thread A locks resource 1 first, and then locks resource 2. Statements 3 and 4 indicate that thread B locks resource 2 first and then locks resource 1, and the conditions for deadlock are met.

3、Deadlock solution

​Guaranteed to lock in the same order.

4、Deadlock Necessary Conditions 5、Solution

There are four main methods:

Ostrich strategy

Buried your head in the sand and pretended nothing was wrong.

Because of the high cost of solving the deadlock problem, the ostrich strategy, which does not take task measures, will achieve higher performance.

When a deadlock occurs, it will not have much impact on the user, or the probability of a deadlock is very low, and the ostrich strategy can be used.

Most operating systems, including Unix, Linux, and Windows, deal with deadlock by simply ignoring it.

Deadlock detection and deadlock recovery

Do not attempt to prevent deadlocks, but take action to recover when deadlocks are detected.

1、Deadlock detection for one resource per type

图片[12]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

The above figure is a resource allocation diagram, in which the boxes represent resources and the circles represent processes. A resource pointing to a process indicates that the resource has been allocated to the process, and a process pointing to a resource indicates that the process requests to acquire the resource.

Figure a can extract the ring, as shown in Figure b, it satisfies the loop waiting condition, so a deadlock occurs.

The deadlock detection algorithm of one resource per type is realized by detecting whether there is a cycle in the directed graph, starting from a node, performing a depth-first search, and marking the visited nodes. If the already marked nodes are visited, It means that there is a cycle in the directed graph, that is, the occurrence of deadlock is detected.

2、Deadlock detection for multiple resources of each type

图片[12]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

In the above figure, there are three processes and four resources, and the meaning of each data is as follows:

The resources requested by both process P1 and P2 cannot be satisfied, only process P3 can, let P3 execute, and then release the resources owned by P3, at this time A = (2 2 2 0). P2 can execute , the resources owned by P2 are released after execution, A = (4 2 2 1) . P1 can also be executed. All processes can be executed smoothly without deadlock.

The algorithm is summarized as follows:

Each process is not marked at the beginning, and the execution process may be marked. When the algorithm ends, any process that is not marked is a deadlocked process.

Find an unmarked process Pi whose requested resource is less than or equal to A. If such a process is found, add the ith row vector of the C matrix to A, mark the process, and turn back to 1. If there is no such process, the algorithm terminates. 6、Deadlock Recovery 7、Deadlock Prevention

Prevent deadlocks from occurring before the program runs.

Break the mutual exclusion condition

​For example, spooling printer technology allows several processes to output simultaneously. The only process that actually requests a physical printer is the printer daemon.

Break request and hold condition

​One way to do this is to specify that all processes request all the resources they need before starting execution.

Break without deprivation

​Allow preemption of resources

Breaking loop request waiting

​Uniform numbering for resources, and processes can only request resources in numbered order.

8、Deadlock Avoidance

Avoid deadlocks while the program is running.

Security status

图片[14]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

The second column of Figure a, Has, represents the number of resources already owned, the third column, Max, represents the total number of resources needed, and Free represents the number of resources that can be used. Starting from Figure a, first let B have all the resources it needs (Figure b), release B after the operation, and Free becomes 5 (Figure c); then run C and A in the same way, so that all processes can run successfully, so the state shown in Figure a can be said to be safe.

Definition: A state is said to be safe if no deadlock occurs, and there is still some scheduling order that enables each process to complete its execution even if all processes suddenly request the greatest demand for resources.

The detection of the safe state is similar to the detection of deadlock, because the safe state must require that no deadlock can occur. The following banker’s algorithm is very similar to the deadlock detection algorithm and can be combined for reference and comparison.

Banker’s algorithm for a single resource

一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。

图片[15]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

上图 c 为不安全状态,因此算法会拒绝之前的请求,从而避免进入图 c 中的状态。

多个资源的银行家算法

图片[16]-win服务器 内存释放 
在校招中顺利拿到更好的offer,你准备好了吗?-唐朝资源网

上图中有五个进程,四个资源。左边的图表示已经分配的资源,右边的图表示还需要分配的资源。最右边的 E、P 以及 A 分别表示:总资源、已分配资源以及可用资源,注意这三个为向量,而不是具体数值,例如 A=(1020),表示 4 个资源分别还剩下 1/0/2/0。

4、检查一个状态是否安全的算法如下:

如果一个状态不是安全的,需要拒绝进入这个状态。

60、为什么分段式存储管理有外部碎片而无内部碎片?为什么固定分区分配有内部碎片而不会有外部碎片?

分段式分配是按需分配,而固定式分配是固定分配的方式。

© 版权声明
THE END
喜欢就支持一下吧
点赞248赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容