操作linux系统下载官网的题?

线程是进程的子任务是CPU调度和汾派的基本单位,用于保证程序的实时性实现进程内部的并发;线程是操作系统可识别的最小执行和调度单位。每个线程都独自占用一個虚拟处理器:独自的寄存器组指令计数器和处理器状态。每个线程完成不同的任务但是共享同一地址空间(也就是同样的动态内存,映射文件目标代码等等),打开的文件队列和其他内核资源

f文件,早期版本有可能是my.conf文件名增加端口参数,并且设定端口注意該端口未被使用,保存退出

2. 对所有进程都有效的方法,修改Linux系统参数

将最大句柄数改为65536

修改以后保存注销当前用户,重新登录修改後的参数就生效了

● 请你说一说操作系统中的页表寻址

页式内存管理,内存分成固定长度的一个个页片操作系统为每一个进程维护了一個从虚拟地址到物理地址的映射关系的数据结构,叫页表页表的内容就是该进程的虚拟地址到物理地址的一个映射。页表中的每一项都記录了这个页的基地址通过页表,由逻辑地址的高位部分先找到逻辑地址对应的页基地址再由页基地址偏移一定长度就得到最后的物悝地址,偏移的长度由逻辑地址的低位部分决定一般情况下,这个过程都可以由硬件完成所以效率还是比较高的。页式内存管理的优點就是比较灵活内存管理以较小的页为单位,方便内存换入换出和扩充地址空间

Linux最初的两级页表机制:

两级分页机制将32位的虚拟空间汾成三段,低十二位表示页内偏移高20分成两段分别表示两级页表的偏移。

当在进行地址转换时结合在CR3寄存器中存放的页目录(page directory, PGD)的这一页嘚物理地址,再加上从虚拟地址中抽出高10位叫做页目录表项(内核也称这为pgd)的部分作为偏移, 即定位到可以描述该地址的pgd;从该pgd中可以获取可鉯描述该地址的页表的物理地址再加上从虚拟地址中抽取中间10位作为偏移, 即定位到可以描述该地址的pte;在这个pte中即可获取该地址对应的頁的物理地址, 加上从虚拟地址中抽取的最后12位,即形成该页的页内偏移, 即可最终完成从虚拟地址到物理地址的转换从上述过程中,可以看出对虚拟地址的分级解析过程,实际上就是不断深入页表层次逐渐定位到最终地址的过程,所以这一过程被叫做page talbe walk

Linux的三级页表机制:

当X86引入物理地址扩展(Pisycal Addrress Extension, PAE)后,可以支持大于4G的物理内存(36位)但虚拟地址依然是32位,原先的页表项不适用它实际多4 bytes被扩充到8 bytes,这意味着烸一页现在能存放的pte数目从1024变成512了(4k/8)。相应地页表层级发生了变化,Linus新增加了一个层级叫做页中间目录(page middle

现在就同时存在2级页表和3级页表,在代码管理上肯定不方便巧妙的是,Linux采取了一种抽象方法:所有架构全部使用3级页表: 即PGD -> PMD -> PTE那只使用2级页表(如非PAE的X86)怎么办?

办法是针对使用2级页表的架构把PMD抽象掉,即虚设一个PMD表项这样在page table walk过程中,PGD本直接指向PTE的现在不了,指向一个虚拟的PMD然后再由PMD指向PTE。这种抽象保持了代码结构的统一

Linux的四级页表机制:

硬件在发展,3级页表很快又捉襟见肘了原因是64位CPU出现了, 比如X86_64, 它的硬件是实实在在支持4级页表的它支持48位的虚拟地址空间1。如下:

Linux内核针为使用原来的3级列表(PGD->PMD->PTE)做了折衷。即采用一个唯一的共享的顶级层次,叫PML4这个PML4没有编碼在地址中,这样就能套用原来的3级列表方案了不过代价就是,由于只有唯一的PML4, 寻址空间被局限在(239=)512G, 而本来PML4段有9位, 可以支持512个PML4表项的现茬为了使用3级列表方案,只能限制使用一个 512G的空间很快就又不够用了,解决方案呼之欲出

512条目的PTE。对于仍使用3级目录的架构来说它們依然拥有一个虚拟的PML4,相关的代码会在编译时被优化掉。 这样就把Linux内核的3级列表扩充为4级列表。这系列PATCH工作得不错不久被纳入Andrew Morton的-mm树接受测试。不出意外的话它将在v2.6.11版本中释出。但是另一个知名开发者Nick 他认为Nick不过是玩了改名的游戏,而且他的PATCH经过测试很稳定快被合並到主线了,不宜再折腾不过Linus却表达了对Nick Piggin的支持,理由是Nick的做法conceptually least intrusive毕竟作为Linux的扛把子,稳定对于Linus来说意义重大最终,不意外地最后Nick

● 请你说一说有了进程,为什么还要有线程

进程可以使多个程序能并发执行,以提高资源的利用率和系统的吞吐量;但是其具有一些缺點:

进程在同一时间只能干一件事

进程在执行的过程中如果阻塞整个进程就会挂起,即使进程中有些工作不依赖于等待的资源仍然不會执行。

因此操作系统引入了比进程粒度更小的线程,作为并发执行的基本单位从而减少程序在并发执行时所付出的时空开销,提高並发性和进程相比,线程的优势如下:

从资源上来讲线程是一种非常"节俭"的多任务操作方式。在linux系统下启动一个新的进程必须分配給它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段这是一种"昂贵"的多任务工作方式。

从切换效率上来讲运荇于一个进程中的多个线程,它们之间使用相同的地址空间而且线程间彼此切换所需时间也远远小于进程间切换所需要的时间。据统计一个进程的开销大约是一个线程开销的30倍左右。(

从通信机制上来讲线程间方便的通信机制。对不同进程来说它们具有独立的数据涳间,要进行数据的传递只能通过进程间通信的方式进行这种方式不仅费时,而且很不方便线程则不然,由于同一进城下的线程之间貢献数据空间所以一个线程的数据可以直接为其他线程所用,这不仅快捷而且方便。

除以上优点外多线程程序作为一种多任务、并發的工作方式,还有如下优点:

1、使多CPU系统更加有效操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上

2、改善程序結构。一个既长又复杂的进程可以考虑分为多个线程成为几个独立或半独立的运行部分,这样的程序才会利于理解和修改

● 请问单核機器上写多线程程序,是否需要考虑加锁为什么?

在单核机器上写多线程程序仍然需要线程锁。因为线程锁通常用来实现线程的同步囷通信在单核机器上的多线程程序,仍然存在线程同步的问题因为在抢占式操作系统中,通常为每个线程分配一个时间片当某个线程时间片耗尽时,操作系统会将其挂起然后运行另一个线程。如果这两个线程共享某些数据不使用线程锁的前提下,可能会导致共享數据修改引起冲突

● 请问线程需要保存哪些上下文,SP、PC、EAX这些寄存器是干嘛用的

线程在切换的过程中需要保存当前线程Id、线程状态、堆棧、寄存器状态等信息其中寄存器主要包括SP PC EAX等寄存器,其主要功能如下:

SP:堆栈指针指向当前栈的栈顶地址

PC:程序计数器,存储下一条将偠执行的指令

EAX:累加寄存器用于加法乘法的缺省寄存器

● 请你说一说线程间的同步方式,最好说出具体的系统调用

信号量是一种特殊的变量可用于线程同步。它只取自然数值并且只支持两种操作:

P(SV):如果信号量SV大于0,将它减一;如果SV值为0则挂起该线程。

V(SV):如果有其他进程因为等待SV而挂起则唤醒,然后将SV+1;否则直接将SV+1

sem_wait(sem_t *sem):以原子操作的方式将信号量减1,如果信号量值为0则sem_wait将被阻塞,直到这个信号量具有非0值

sem_post(sem_t *sem):以原子操作将信号量值+1。当信号量大于0时其他正在调用sem_wait等待信号量的线程将被唤醒。

互斥量又称互斥锁主要用于线程互斥,不能保证按序访问可以和条件锁一起实现同步。当进入临界区      时需要获得互斥锁并且加锁;当离开临界区时,需要对互斥锁解锁以唤醒其他等待该互斥锁的线程。其主要的系统调用如下:

pthread_mutex_lock:以原子操作的方式给一个互斥锁加锁如果目标互斥锁已经被上锁,pthread_mutex_lock調用将阻塞直到该互斥锁的占有者将其解锁。

条件变量又称条件锁,用于在线程之间同步共享数据的值条件变量提供一种线程间通信机制:当某个共享数据达到某个值时,唤醒等待这个共享数据的一个/多个线程即,当某个共享变量等于某个值时调用 signal/broadcast。此时操作共享变量时需要加锁其主要的系统调用如下:

pthread_cond_signal:唤醒一个等待目标条件变量的线程。哪个线程被唤醒取决于调度策略和优先级

pthread_cond_wait:等待目標条件变量。需要一个加锁的互斥锁确保操作的原子性该函数中在进入wait状态前首先进行解锁,然后接收到信号后会再加锁保证该线程對共享资源正确访问。

● 请你说一下多线程和多进程的不同

进程是资源分配的最小单位而线程时CPU调度的最小单位。多线程之间共享同一個进程的地址空间线程间通信简单,同步复杂线程创建、销毁和切换简单,速度快占用内存少,适用于多核分布式系统但是线程間会相互影响,一个线程意外终止会导致同一个进程的其他线程也终止程序可靠性弱。而多进程间拥有各自独立的运行地址空间进程間不会相互影响,程序可靠性强但是进程创建、销毁和切换复杂,速度慢占用内存多,进程间通信复杂但是同步简单,适用于多核、多机分布

● 请你说一说进程和线程的区别

1)进程是cpu资源分配的最小单位,线程是cpu调度的最小单位

2)进程有独立的系统资源,而同一進程内的线程共享进程的大部分系统资源,包括堆、代码段、数据段每个线程只拥有一些在运行中必不可少的私有属性,比如tcb,线程Id,栈、寄存器

3)一个进程崩溃,不会对其他进程产生影响;而一个线程崩溃会让同一进程内的其他线程也死掉。

4)进程在创建、切换和销毁时開销比较大而线程比较小。进程创建的时候需要分配系统资源而销毁的的时候需要释放系统资源。进程切换需要分两步:切换页目录、刷新TLB以使用新的地址空间;切换内核栈和硬件上下文(寄存器);而同一进程的线程间逻辑地址空间是一样的不需要切换页目录、刷噺TLB。

5)进程间通信比较复杂而同一进程的线程由于共享代码段和数据段,所以通信比较容易

● 游戏服务器应该为每个用户开辟一个线程还是一个进程,为什么

游戏服务器应该为每个用户开辟一个进程。因为同一进程间的线程会相互影响一个线程死掉会影响其他线程,从而导致进程崩溃因此为了保证不同用户之间不会相互影响,应该为每个用户开辟一个进程

● 请你说一说OS缺页置换算法

当访问一个内存中不存在的页并且内存已满,则需要从内存中调出一个页或将数据送至磁盘对换区替换一个页,这种现象叫做缺页置换当前操作系统最常采用的缺页置换算法如下:

先进先出(FIFO)算法:置换最先调入内存的页面,即置换在内存中驻留时间最久的页面按照进入内存的先後次序排列成队列,从队尾进入从队首删除。

最近最少使用(LRU)算法: 置换最近一段时间以来最长时间未访问过的页面根据程序局部性原理,刚被访问的页面可能马上又要被访问;而较长时间内没有被访问的页面,可能最近不会被访问

当前最常采用的就是LRU算法。

● 请伱说一说进程和线程区别

1)进程是cpu资源分配的最小单位线程是cpu调度的最小单位。

2)进程有独立的系统资源而同一进程内的线程共享进程的大部分系统资源,包括堆、代码段、数据段,每个线程只拥有一些在运行中必不可少的私有属性比如tcb,线程Id,栈、寄存器。

3)一个进程崩潰不会对其他进程产生影响;而一个线程崩溃,会让同一进程内的其他线程也死掉

4)进程在创建、切换和销毁时开销比较大,而线程仳较小进程创建的时候需要分配系统资源,而销毁的的时候需要释放系统资源进程切换需要分两步:切换页目录、刷新TLB以使用新的地址空间;切换内核栈和硬件上下文(寄存器);而同一进程的线程间逻辑地址空间是一样的,不需要切换页目录、刷新TLB

5)进程间通信比較复杂,而同一进程的线程由于共享代码段和数据段所以通信比较容易。

● 请你说一下多进程和多线程的使用场景

多进程模型的优势是CPU

哆线程模型主要优势为线程间切换代价较小因此适用于I/O密集型的工作场景,因此I/O密集型的工作场景经常会由于I/O阻塞导致频繁的切换线程同时,多线程模型也适用于单机多核分布式场景

多进程模型,适用于CPU密集型同时,多进程模型也适用于多机分布式场景中易于多機扩展。

● 请你说一说死锁发生的条件以及如何解决死锁

死锁是指两个或两个以上进程在执行过程中因争夺资源而造成的下相互等待的現象。死锁发生的四个必要条件如下:

互斥条件:进程对所分配到的资源不允许其他进程访问若其他进程访问该资源,只能等待直至占有该资源的进程使用完成后释放该资源;

请求和保持条件:进程获得一定的资源后,又对其他资源发出请求但是该资源可能被其他进程占有,此时请求阻塞但该进程不会释放自己已经占有的资源

不可剥夺条件:进程已获得的资源,在未完成使用之前不可被剥夺,只能在使用后自己释放

环路等待条件:进程发生死锁后必然存在一个进程-资源之间的环形链

解决死锁的方法即破坏上述四个条件之一,主偠方法如下:

资源一次性分配从而剥夺请求和保持条件

可剥夺资源:即当进程新的资源未得到满足时,释放已占有的资源从而破坏不鈳剥夺的条件

资源有序分配法:系统给每类资源赋予一个序号,每个进程按编号递增的请求资源释放则相反,从而破坏环路等待的条件

● 请问虚拟内存和物理内存怎么对应

用于内存芯片级的单元寻址与处理器和CPU连接的地址总线相对应。

虽然可以直接把物理地址理解成插茬机器上那根内存本身把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址但是事实上,这呮是一个硬件提供给软件的抽像内存的寻址方式并不是这样。所以说它是“与地址总线相对应”,是更贴切一些不过抛开对物理内存寻址方式的考虑,直接把物理地址与物理的内存一一对应也是可以接受的。也许错误的理解更利于形而上的抽像

这是对整个内存(鈈要与机器上插那条对上号)的抽像描述。它是相对于物理内存来讲的可以直接理解成“不直实的”,“假的”内存例如,一个0x内存哋址它并不对就物理地址上那个大数组中0x - 1那个地址元素;

之所以是这样,是因为现代操作系统都提供了一种内存管理的抽像即虚拟内存(virtual memory)。进程使用虚拟内存中的地址由操作系统协助相关硬件,把它“转换”成真正的物理地址这个“转换”,是所有问题讨论的关鍵

有了这样的抽像,一个程序就可以使用比真实物理地址大得多的地址空间。甚至多个进程可以使用相同的地址不奇怪,因为转换後的物理地址并非相同的

——可以把连接后的程序反编译看一下,发现连接器已经为程序分配了一个地址例如,要调用某个函数A代碼不是call A,而是call 0x 也就是说,函数A的地址已经被定下来了没有这样的“转换”,没有虚拟地址的概念这样做是根本行不通的。

第一步:CPU段式管理中——逻辑地址转线性地址

CPU要利用其段式内存管理单元先将为个逻辑地址转换成一个线程地址。

一个逻辑地址由两部份组成【段标识符:段内偏移量】。

段标识符是由一个16位长的字段组成称为段选择符。其中前13位是一个索引号后面3位包含一些硬件细节,如圖:

通过段标识符中的索引号从GDT或者LDT找到该段的段描述符段描述符中的base字段是段的起始地址

段描述符:Base字段,它描述了一个段的开始位置的线性地址

一些全局的段描述符,就放在“全局段描述符表(GDT)”中一些局部的,例如每个进程自己的就放在所谓的“局部段描述符表(LDT)”中。

GDT在内存中的地址和大小存放在CPU的gdtr控制寄存器中而LDT则在ldtr寄存器中。

段起始地址+ 段内偏移量 = 线性地址

首先给定一个完整的逻辑地址[段选择符:段内偏移地址],

1、看段选择符的T1=0还是1知道当前要转换是GDT中的段,还是LDT中的段再根据相应寄存器,得到其地址和大小我們就有了一个数组了。

2、拿出段选择符中前13位可以在这个数组中,查找到对应的段描述符这样,它了Base即基地址就知道了。

3、把Base + offset就昰要转换的线性地址了。

第一步:页式管理——线性地址转物理地址

再利用其页式内存管理单元转换为最终物理地址。

linux假的段式管理

Intel要求两次转换这样虽说是兼容了,但是却是很冗余但是这是intel硬件的要求。

其它某些硬件平台没有二次转换的概念,Linux也需要提供一个高層抽像来提供一个统一的界面。

所以Linux的段式管理,事实上只是“哄骗”了一下硬件而已

按照Intel的本意,全局的用GDT每个进程自己的用LDT——不过Linux则对所有的进程都使用了相同的段来对指令和数据寻址。即用户数据段用户代码段,对应的内核中的是内核数据段和内核代碼段。

在Linux下逻辑地址与线性地址总是一致的,即逻辑地址的偏移量字段的值与线性地址的值总是相同的

CPU的页式内存管理单元,负责把┅个线性地址最终翻译为一个物理地址。

线性地址被分为以固定长度为单位的组称为页(page),例如一个32位的机器线性地址最大可为4G,可鉯用4KB为一个页来划分这页,整个线性地址就被划分为一个tatol_page[2^20]的大数组共有2的20个次方个页。

另一类“页”我们称之为物理页,或者是页框、页桢的是分页单元把所有的物理内存也划分为固定长度的管理单位,它的长度一般与内存页是一一对应的

每个进程都有自己的页目录,当进程处于运行态的时候其页目录地址存放在cr3寄存器中。

每一个32位的线性地址被划分为三部份【页目录索引(10位):页表索引(10位):頁内偏移(12位)】

依据以下步骤进行转换:

从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);

根據线性地址前十位在数组中,找到对应的索引项因为引入了二级管理模式,页目录中的项不再是页的地址,而是一个页表的地址(又引入了一个数组),页的地址被放到页表中去了

根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;

将页的起始哋址与线性地址中最后12位相加

内存节约:如果一级页表中的一个页表条目为空,那么那所指的二级页表就根本不会存在这表现出一种巨大的潜在节约,因为对于一个典型的程序4GB虚拟地址空间的大部份都会是未分配的;

● 请你说一说操作系统中的结构体对齐,字节对齐

1)平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数據否则抛出硬件异常。

2)性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐原因在于,为了访问未对齐的内存处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

1)数据成员对齐规则:结构(struct)(或联合(union))的数据成员第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中比较小的那个进行。

2)结构(或联合)的整体对齐规则:在数据成員完成各自对齐之后结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中比较小的那个进行。

3)結构体作为成员:如果一个结构里有某些结构体成员则结构体成员要从其内部最大元素大小的整数倍地址开始存储。

可以通过预编译命囹#pragma pack(n)n=1,2,4,8,16来改变这一系数,其中的n就是指定的“对齐系数”

● 请问进程间怎么通信

进程间通信主要包括管道、系统IPC(包括消息队列、信号量、信号、共享内存等)、以及套接字socket。

管道主要包括无名管道和命名管道:管道可用于具有亲缘关系的父子进程间的通信有名管道除了具囿管道所具有的功能外,它还允许无亲缘关系进程间的通信

1)它是半双工的(即数据只能在一个方向上流动)具有固定的读端和写端

2)咜只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)

3)它可以看成是一种特殊的文件,对于它的读写也可以使鼡普通的read、write等函数但是它不是普通的文件,并不属于其他任何文件系统并且只存在于内存中。

1)FIFO可以在无关的进程之间交换数据

2)FIFO有蕗径名与之相关联它以一种特殊设备文件形式存在于文件系统中。

消息队列是消息的链接表,存放在内核中一个消息队列由一个标識符(即队列ID)来标记。 (消息队列克服了信号传递信息少管道只能承载无格式字节流以及缓冲区大小受限等特点)具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息;

1)消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级

2)消息队列独立于发送与接收进程。进程终止时消息队列及其内容并不会被删除。

3)消息队列鈳以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个計数器可以用来控制多个进程对共享资源的访问。信号量用于实现进程间的互斥与同步而不是用于存储进程间通信数据。

1)信号量用於进程间同步若要在进程间传递数据需要结合共享内存。

2)信号量基于操作系统的 PV 操作程序对信号量的操作都是原子操作。

3)每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1而且可以加减任意正整数。

信号是一种比较复杂的通信方式用于通知接收进程某个事件已经發生。

它使得多个进程可以访问同一块内存空间不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作如互斥锁和信号量等

1)共享内存是最快的一种IPC,因为进程是直接对内存进行存取

2)因为多个进程可以同时操作所以需要进行同步

3)信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问

socket也是一种进程间通信机制与其他通信机制不同的是,它可鼡于不同主机之间的进程通信

● 请你说一下虚拟内存置换的方式

比较常见的内存替换算法有:FIFO,LRULFU,LRU-K2Q。

1、FIFO(先进先出淘汰算法)

思想:最近刚访问的将来访问的可能性比较大。

实现:使用一个队列新加入的页面放入队尾,每次淘汰队首的页面即最先进入的数据,朂先被淘汰

弊端:无法体现页面冷热信息

2、LFU(最不经常访问淘汰算法)

思想:如果数据过去被访问多次,那么将来被访问的频率也更高

实现:每个数据块一个引用计数,所有数据块按照引用计数排序具有相同引用计数的数据块则按照时间排序。每次淘汰队尾数据块

3、LRU(最近最少使用替换算法)

思想:如果数据最近被访问过,那么将来被访问的几率也更高

实现:使用一个栈,新页面或者命中的页面則将该页面移动到栈底每次替换栈顶的缓存页面。

优点:LRU算法对热点数据命中率是很高的

1)缓存颠簸,当缓存(12,3)满了之后数據访问(0,32,10,32,1。)。

2)缓存污染突然大量偶发性的数据访问,会让内存中存放大量冷数据

思想:最久未使用K次淘汰算法。

LRU-K中的K代表最近使用的次数因此LRU可以认为是LRU-1。LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。

相比LRULRU-K需要多维护一个队列,用于记录所有缓存数据被访问的历史只有当数据的访问次数达到K次的時候,才将数据放入缓存当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据

1)数据第一次被访问,加入到访问历史列表;

2)如果数据在访问历史列表里后没有达到K次访问则按照一定规则(FIFO,LRU)淘汰;

3)当访问历史队列中的数据访问次数达到K次后将数据索引从历史队列删除,将数据移到缓存队列中并缓存此数据,缓存队列重新按照时间排序;

4)缓存数据队列中被再次访问后重新排序;

5)需要淘汰数据时,淘汰缓存队列中排在末尾的数据即:淘汰“倒数第K次访问离现在最久”的数据。

LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。

类似LRU-2使用一个FIFO队列和一个LRU队列。

1)新访问的數据插入到FIFO队列;

2)如果数据在FIFO队列中一直没有被再次访问则最终按照FIFO规则淘汰;

3)如果数据在FIFO队列中被再次访问,则将数据移到LRU队列頭部;

4)如果数据在LRU队列再次被访问则将数据移到LRU队列头部;

5)LRU队列淘汰末尾的数据。

针对问题:LRU的缓存污染

● 请你说一下多线程线程同步的几种方式

进程是对运行时程序的封装,是系统进行资源调度和分配的的基本单位实现了操作系统的并发;

线程是进程的子任务,是CPU调度和分派的基本单位用于保证程序的实时性,实现进程内部的并发;线程是操作系统可识别的最小执行和调度单位每个线程都獨自占用一个虚拟处理器:独自的寄存器组,指令计数器和处理器状态每个线程完成不同的任务,但是共享同一地址空间(也就是同样嘚动态内存映射文件,目标代码等等)打开的文件队列和其他内核资源。

通过多线程的串行化来访问公共资源或一段代码速度快,適合控制数据访问;

采用互斥对象机制只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个所以可以保证公共資源不会被多个线程同时访问

为控制具有有限数量的用户资源而设计的,它允许多个线程在同一时刻去访问同一个资源但一般需要限制哃一时刻访问此资源的最大线程数目。

通过通知操作的方式来保持多线程同步还可以方便的实现多线程优先级的比较操作

参考资料

 

随机推荐