操作系统
一、进程与线程的概念,以及为什么要有进程线程,它们有什么区别
1.基本概念:
进程是对运行程序的封装,是系统进行资源调度和分配的基本单位,实现了操作系统的并发。
线程是进程的子任务,是CPU调度和分派的基本单位,实现进程内部的并发。
2.区别
一个线程能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程依赖进程而存在。
**进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。**资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量)、数据段(全局变量和静态变量)、扩展堆(堆存储)。但是每个线程拥有自己的的栈顶,又叫运行时段,用来存储所有局部变量和临时变量。
进程切换的开销远大于线程切换的开销。在进行进程切换时,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU环境的设置;而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。
二、进程和线程间通信
1.进程
1.管道
无名管道:它是半双工(数据只能在一个方向上流动);具有固定的读端和写端,并且只用用于具有亲缘关系(父子、兄弟)的进程之间的通信。
有名管道:可以在无关的进程之间交换数据。
2.系统IPC
1.消息队列
是消息的链接表,存放在内核中,一个消息队列有一个标识符(队列ID)来标记;消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点。消息队列对立与发送和接受进程。进程终止时,消息队列及其内容并不会被删除;并且可以实现消息的随即查询,不一定要按照先进先出的次序读取,也可以按消息的类型读取。
2.信号量
是一个计数器,可以用来控制多个进程对资源共享的访问,用于实现进程间的互斥与同步,若要在进程间传递数据需要结合共享内存。
3.信号
信号是一种比较复杂的通信方式,用于通知接受进程某个事件已经发生。
4.共享内存
它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新(需要互斥锁或信号量的支持)。信号量和共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
3.套接字socket
可用于不同主机之间的进程通信。
2.线程
1.临界区
通过多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2.互斥量
采用互斥锁对象机制,只有拿到这个锁的线程才能访问公共资源的权限。
3.信号量
它允许多个线程在同一时刻去访问同一个数据,但一般需要限制同一时刻访问此资源的最大线程数。
4.事件
通过通知操作的方式来保持多线程同步,还可以方便实现多线程优先级的比较操作。
三、虚拟内存
1.为什么会有虚拟内存
电脑中所运行的程序均需经由内存执行,若执行的程序占用内存很大或很多,
则会导致内存消耗殆尽。为解决这问题,WIndows中运行了虚拟内存,即匀出一部
分硬盘空间来充当内存使用,以缓解内存的紧张。若计算机运行程序或操作所需的
随机存储器(RAM)不足时,则Windows会用虚拟内存进行补偿。他将计算机的
RAM和硬盘上的临时空间组合。当RAM运行速率缓慢时,他便将数据从RAM移动到
称为“分页文件”的空间中。将数据移入分页文件中来释放RAM,以便完成工作。
一般而言,计算机的RAM容量越大,程序运行越快。若计算机的速率由于RAM可用
空间匮乏而减慢,则可尝试通过增加虚拟内存来补偿。最好的方法还是加内存条。
2.什么是虚拟地址空间?
虚拟地址空间就是虚拟内存,是计算机系统内存管理的一种技术,它使得应用程序认为它拥有连续可用的内存(一个连续完成的地址空间),而实际上,它通常是被分割成多个物理内存碎片,还有部分暂时存储在外部磁盘的存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型系统的编写变得更容易对真正的物理内存(RAM)的使用功能也更有效率。
3.虚拟内存的好处
内存保护:每个进程运行在各自的虚拟内存地址空间,互相不能干扰对方虚拟内存还对特定的内存地址提供写保护,可以防止代码或主句被恶意篡改。公平内存分配:采用了虚拟内存之后,每个进程都相当于有同样大小的虚拟空间。
当进程通信时,可采用虚拟共享的方式实现。
节省内存:当不同的进程使用相同的代码时,比如库文件中的代码,物理内存中著需要存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射进去就可以了,节省内存。
可以利用碎片化空间:在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片。
4.虚拟内存和物理内存的区别
1.作用不同
物理内存是在计算运行时为操作系统和各个程序提供临时存储。
虚拟内存使得应用程序认为拥有连续可用的内存。
2.特点不同
物理内存直接决定了电脑同时运行多少个程序的流畅度,会对系统的虚拟内存限制有影响。虚拟内存的大小=物理内存容量+所有页面文件的最大容量。
虚拟内存:被分割成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
3.主体不同
物理内存指的是通过物理内存条而获得的内存空间。
虚拟内存是计算机系统内存管理的一种技术。是操作系统作为内存而使用的一部分硬盘空间。
四、程序的内存结构
1.堆
用于动态分配内存,由程序员申请分配和释放。堆是从低地址向高地址位增长,采用链式存储结构。当申请堆空间时库函数是按照一定算法搜索可用的足够大的空间,因此堆的效率比栈要低。
2.栈
由编译器自动释放,存放函数的参数值、局部变量等。每当一个函数被调用时,该函数的返回类型和一些被调用的信息存放在栈中。然后这个被调用的函数在为他的自动变量和临时变量在栈上分配空间。每调用一个函数一个新的栈就会被使用。
3.数据段
存放程序中已初始化的全局变量的一块内存区域,数据段也属于静态内存分配。
4.代码段
存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域属于只读,在代码段中,也有可能包含一些只读的常数变量。
5.BBS未初始化的数据区
通常用来存储程序中未初始化的全局变量和静态变量的一块内存区域。BBS段属于静态分布,程序结束后静态变量资源由系统自动释放。
五、缺页中断
1.什么是缺页中断
缺页中断就是要访问的页不在主存,需要操作系统将其调入主存后再进行访问。
在请求分页系统中,可以通过查询页表中的状态位来确定所要访问的页是否存在与主存中,每当要访问的页不在主存中,会产生一次缺页中断,此时操作系统会根据页表中的外存地址在外存中找多所缺的一页,将其调入内存。
2.缺页中断的处理步骤
1.保护CPU现场。
2.分析中断原因。
3.转入缺页中断处理程序进行处理。
4.恢复CPU现场,继续执行。
3.常见的页面置换算法
当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移除内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则就是页面置换算法
1.最佳置换算法(OPT)
从主存中移除永远不再需要的页面或者未来最长时间内不再被访问的页面,该算法保证了可以获得最低缺页率,但无法预知未来页面的使用情况,因此目前无法实现。但常用来评价其他算法
2.先进先出置换算法(FIFO)
当需要淘汰一个页面时,总是选择驻留在主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰,因为最早调入主存的页面不再被使用的可能性最大。
3.最近最久未使用算法(LRU)
选择之前最长时间未使用的页面置换。
4.最不常用页面置换算法(NFU)
用一个软件模拟LRU,该算法将每个页面和一个软件计数器相关联,计数器的初值为0,每次时钟中断时,由操作系统扫描内存中所有的页面,将每个页面的R位加到他的计数器上,这个计数器大体上跟踪了各个页面被访问的频繁程度。当发生缺页中断时,则置换计数器值最小的页面。
六、死锁的发生条件及如何解决死锁
死锁指的是两个或两个以上进程在执行过程中,因争夺资源而造成的互相等待的现象。有四个必要条件。
1.互斥条件
进程对分配到的资源不允许其他进程访问,若其他进程访问该资源,只能等待,直到占用该资源的进程使用完成后释放该资源。
2.请求和保持条件
进程获得一定资源后,又对其他资源发出请求,但是该资源可能被其他进程占有,此时请求阻塞,但该进程不会释放自己已占有的资源。
3.不可剥夺条件
进程以获得的资源,在未使用完成之前,不可被剥夺,只能在使用后自己释放。
4.环路等待条件
进程发生死锁后,必然存在着一个进程->资源之间形成的环形链。
解决死锁的方式即破坏上述条件之一
1.资源一次性分配,从而剥夺请求和保持条件。
2.可剥夺资源:即当进程新的资源未得到满足时,释放已占有的资源,从而破坏不可剥夺的条件。
3.资源有序分配法:系统给每类资源赋予一个序号,每个进程按编号递增的去请求资源,释放则相反,从而破坏环路等待的条件。
七、什么是银行家算法
允许进程动态的申请资源,系统在每次实施资源分配之前,先计算资源分配的安全性,若此次资源分配安全(即资源分配周期,系统能按某种顺序来为每个进程分配其所需的资源,直到最大需求,使每个进程都可以顺利完成),便将资源分配给进程,否则不分配资源,让进程等待.
银行家算法是避免死锁的一种重要方法。操作系统按照指定规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足他的最大需求量则按照当前的申请分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过了该进程对资源的最大需求量。若超过则拒绝分配资源,若没有超过,则在测试系统现存的资源能否满足该进程尚需的最大资源量,若满足则按当前申请分配资源,否则也要推迟分配。
八、操作系统中的锁
1.互斥锁
用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒。
2.读写锁
处于读操作时,可以允许多个线程同时获得读操作,但同一时刻只能有一个线程获得写锁,其他获得写锁失败的线程都会进入睡眠状态,直到写锁被释放时唤醒。
写锁会阻塞其他读写锁,当有一线程获得写锁再写时,读锁也不能被其他线程获得。
读锁会阻塞写,但不会阻塞读
写锁会把读写都阻塞。
3.自旋锁
在任何时刻同样只能有一个线程访问对象,但是当获取锁操作失败后,不会进入睡眠,而是会在原地自旋,一直尝试获取锁,直到获取。这样节省了线程从睡眠状态到唤醒期间的消耗,在加锁时间短暂的环境下会极大提高效率。但如果加锁时间过长,则会非常浪费CPU资源。
九、内存溢出和内存泄漏
1.内存溢出
指程序申请内存时,没有足够的内存供申请者使用。内存溢出就是你要的内存空间,超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误。
内存溢出的原因
1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据。
2.集合类中有对对象的引用,使用完后未清空,使得不能回收。
3.代码中存在死循环或循环产生过多重复的对象实体。
4.使用第三方软件中的BUG。
5.启动参数内存值设定过小。
2、内存泄露
内存泄露是由于疏忽或错误造成了程序未能释放掉不再使用的内存,内存泄露并非指内存在物理上的消失,而是应用程序分配某段内容后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
堆内存泄露:堆内存指的是程序运行中根据需要分配通过malloc,relloc,new等从堆中分配的一块内存,完成后必须通过调用对应的free或者delete删掉。如果程序的设计的错误导致这部分内存没被释放,那么这次后这块内存将不会被使用。就是发生了内存溢出。
系统资源泄露:主要是指程序使用系统分配的资源比如Bitamp,handler,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统性能降低,系统运行不稳定。
十、Java中的内存泄露
由于Java的JVM引入了垃圾回收机制,垃圾回收器会自动回收不再使用的对象,
JVM回收对象的本质就是判断一个对象是否还被引用,那么对于这种情况,由于
代码的实现不同就会出现很多种的内存泄露(让JVM误以为此对象还在引用种无法
回收,造成内存泄露)。
1.常见的内存泄露问题
1.长声明周期对象持有短生命周期的引用
public calss test{
Object object;
public void test(){
object = new Object();
//...其他代码
}
}
#在这个例子种,test方法结束后,创建出来的object所占有的内存不会被马上认为是可以释放的,就有可能内存泄露。
2.各种连接,如数据库连接、网络连接和IO连接等,没有显示调用close关闭,不被GC回收导致内存泄露。
3.单例对象在被初始化后将JVM的整个生命周期中存在(以静态变量的额方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被JVM正常回收,导致内存泄露。
2.如何避免内存泄露的发生
1.尽量减少使用静态变量,类的静态变量的生命周期和类同步。
2.声明对象引用之前,明确内存对象的有效作用域,尽量减少对象的作用域,将类的成员变量改写为方法内的局部变量。
3.减少长声明周期的对象持有短生命周期的引用。
4.使用StringBuffer和StringBuilder进行字符串连接,String字符串代表的是不可变的字符串,如果使用多个String对象进行字符串连接运算,在运行时可能产生大量临时字符串,这些字符串会保存在内存中导致程序性能下降。
5.对于不需要的对象啊你个手动设置null值,不管GC何时开始清理。
6.各种连接操作,用完之后应该关闭。
十一、协程
携程:是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,
一个线程也可以拥有多个协程。协程不是操作系统内核所管理的,而是完全由程序
控制(用户态执行),因此,不会像线程切换那样消耗资源。
协程不是进程也不是线程,而是一种特殊的函数,这个函数既可以在某个地方挂起
并且可以重新在挂起处继续运行。一个线程的多个协程的运行是串行的,当一个
协程运行时,其他协程必须挂起。
协程在子程序内部是可中断的,然后转而执行别的子程序,在适当的时候在返回来接着执行。
协程和线程一样共享堆,不共享栈,携程就由我们在协程的代码里面显示调度。
一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅线程,线程之间是平行运行的,在线程里面可以开启协程,让程序在特定的时间内运行。
协程的优势:
1.协程避免了无意义的调度,由此提高性能,但也因此,必须我们自己手动调用和承担调度责任,协程也失去了标准使用多CPU的功能。
2.不需要锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
十二、系统调用是什么?
1.概念
系统调用是操作系统提供给用户的一种服务,程序设计人员在编写程序的时候可
以用来请求操作系统的服务。
常见的系统调用:文件相关操作、系统控制、进程控制。
2.内核态和用户态
1.为什么要有内核态和用户态
有时需要限制不同程序之间的访问能力,防止它们获取别的程序的内存数据,或者获取外围设备的数据,并发送到网络,CPU划分出两个权限等级-用户态和内核态。
用户态:也叫普通态,CPU访问资源有限。程序的可靠性、安全性降低。
**内核态:**CPU可以访问计算机的任何资源。程序的可靠性、安全性要求高
用户态如何切换到内核态:
系统调用:对文件进行写操作,open和write都是系统调用。
外围设备中断。
异常。
3.系统调用的工作流程
所有用户程序都是运行在用户态的,但是有时候程序需要做一些内核态的事情,例
如从硬盘读取数据或者从键盘获取输入。而唯一可以做这些事情的就是操作系统
所以此时程序就需要操作系统请求以程序的名义来执行这些操作。
系统调用的工作流程
1.用户态将一些数据值访问在寄存器中,或者使用参数创建一个堆栈,一次表明需要操作系统提供的服务。
2.用户态程序执行陷阱指令。
3.CPU切换到内核态,并跳到位于内存指定位置的指令,这些指令是操作系统的一部分,它们具有内存保护,不可被用户态程序访问。这些指令称之为陷阱或者系统调用处理器,他们会读取程序放入内存的数据参数,并执行程序请求的服务。
4.系统调用完成后,操作系统会重置CPU为用户态返回系统调用的结果。
十三、僵尸进程、孤儿进程、守护进程
在Linux中,正常情况下,子进程是通过父进程拆创建的,子进程在创建新的进程。
子进程的结束和父进程的运行是一个异步过程,即父进程永远也无法预测子进程到
底什么时候结束。当一个进程在完成它的工作终止之后,它的父进程需要调用
wait()或者waitpid()系统调用取得子进程的终止状态。
1.孤儿进程
一个父进程退出,而他的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
2.僵尸进程
一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或者waitpid获取子进程的状态信息,那么子进程的进程描述符任然保存在系统中,这种进程就是僵尸进程。
**查看:**利用ps命令,可以看到有标记为Z的进程就是僵尸进程。
**清除:**杀死父进程,父进程死后,僵尸进程称为孤儿进程,过继给1号进程init。
3.守护进程
守护进程就是在后台运行,不在任何终端关联的进程,通常情况下守护进程在系统启动时就在运行,它们由root用户或者其他特殊用户运行,并能处理一些系统级的任务。
十三、常用的LInux命令
1.ps -ef|grep xxx:查看某个进程的进程号
2.kill:终止一个进程
3.ifconfig:查看所有的网络接口及其状态
4.lsof -i:端口号,查看某个端口是否被占用
5.free:显示系统当前内存的使用情况。
6.find:查找指定文件名的文件
7.top:查看当前系统中占用资源最多的进程。
8.df:显示文件系统的磁盘使用情况,默认情况下df-k将以字节单位输出磁盘的使用量。
十四、操作系统中进程调度算法
周转时间:指作业从提交系统开始,直到作为完成位置的时间间隔
带权周转时间:是指作业周转时间与实际运行服务时间的比值。平均周转时间和
平均带权周转时间是衡量批处理操作系统调度算法的重要原则。
服务时间:作业需要运行的时间
完成时间= 开始时间 - 服务时间
等待时间 = 开始时间 - 提交时间
周转时间 = 完成时间 - 提交时间
带权周转时间 = 周转时间/服务时间
响应比 = (等待时间 + 服务时间) / 服务时间 = 等待时间/服务时间 + 1
1.先来先服务
按照作业进入系统后备作业队列的先后次序来挑选作业,加入就绪队列,等待执行。
先来先服务调度算法是非抢占式的,有利于长期作业
2.短作业优先
短作业优先调度算法用于进程调度时,该算法既可以用户作业调度,也可以用户进程调度。
在作业调度中,该算法每次从后备作业队列中挑选估计服务时间最短的一个或几个作业,将它们调入内存,分配必要的资源,创建进程并放入就绪队列。在进程调度中的原理类似
短作业优先是非抢占式的,优先照顾短作业,降低了平均等待时间,提高吞吐量,但是不利于长作业,长作业可能一直处于等待状态;完全为考虑作业的优先紧迫程度,不能用于实时系统。
3.最短剩余时间优先
短作业优先是非抢占式的,用户抢占式调度系统时,对应的算法称为最短剩余时间优先调度算法。
该算法首先按照作业的服务时间挑选最短的作业运行,在该作业运行期间,一旦有新作也达到系统,并且该新作业的服务时间比当前运行作业剩余时间短,则发生抢占。该算法保证一旦新的短作业进入系统,能够很快得到处理。
由于频繁的抢占和进程切换,系统开销大,一般用于实时系统。
4.高响应比优先
高响应比优先调度算法是非抢占式的。每次作业调度时,先计算后备作业队列中每个作业的响应比,挑选出最高的进入系统。
该算法介于先来先服务和短作业优先两种算法之间,但是每次需要计算每个作业的响应比,增加系统开销
5.时间片轮转
系统将CPU处理时间换分为若干个时间片(q),进程按照到达先后顺序排列,每次
调度选择队首的进程,执行完一个时间片去q后,计时器发出时钟中断请求,该进程
移到队尾。
该算法能在给定的时间内响应到所有用户请求,达到分时系统的目的。
其性能主要取决于时间片q的大小,q太大则所有进程在一个时间片完成。
该算法简单有效,常用于分时系统,但不利于I/O频繁的,由于这种进程用不完一个时间片,就因为等待I/O操作而被阻塞,当I/O操作结束后,之恶能擦汗如到就绪队列的末尾,等待下一轮调度。
十五、操作系统里的内存碎片
内存碎片分为两种:内部碎片和外部碎片。
内部碎片和外部碎片最明显的区别就是内部碎片能明确的指出这部分内存属于哪个进程的,而外部碎片不属于任何进程。
**内部碎片:**是指已经分配给某个进程,但该进程却使用不到的内存空间,只有当该进程运行完毕后才能释放这块内存空间给其他进程使用。
**外部碎片:**指的是还没有被分配出去(不属于任何进程),但由于太小无法分配申请内存空间的新进程的内存空闲区域。
外部碎片是处于任何已分配区域页面外部空心的存储块。这些存储块总和可以满足当前申请长度,但地址不连续,无法申请。
解决办法:
1.利用分页单元把一组非连续的空闲页框映射到连续的线性地址----非连续内存分配(段式、页式、段页式)
2.开发一种适当的技术来记录现存空闲的连续页框块的情况,以尽量满足对小块的请求而分割大的空闲块----伙伴系统
1.伙伴系统:
把所有的空闲页框分组为11个块链表,每个链表分别包含大小为
1,2,4,8,16,32,64,128,256,512,1024个连续的页框中,每个页框大小4kb。每次进程申请内存时,就从比申请规模大的链表中拆除指定内存,将被拆解的块中的剩余部分再进行拆解并插入到指定链表中。
比如现在要申请一个256页框(1M)的块
在256个页框的链表中检查是否有一个空闲块,如果没有,查找下一个更大的块。
在512个页框的链表中检查有没有,有的话,把512个页框的空闲块分为两份,第一份给用户满足要求,第二份链接到256哪个页框的链表。
2.非连续内存分配
非连续内存分配允许一个程序使用非连续的物理地址空间,即一个程序的逻辑地址空间被映射到物理地址空间不同的块,每一块内部是连续的,但块与块之间不可连续核心目标就是提高内存利用率和管理灵活性,允许代码和数据共享
1.段式
操作系统为应用程序设置段表,段表维护了每一个段的基值和长度,用段号(本质就是段的索引)就能查找到对应的段基址和长度。
内存访问顺序如下:CPU计算的时候取出逻辑地址(段号,偏移);用段号去查找出对应的段基址和段长度;判断逻辑地址的偏移和段长度大小关系;如果偏移大于段长度,那么就是内存异常;通过段基址加上逻辑地址偏移,就找到了物理内存的实际地址。
2.页式
页式是比段式更细粒度的策略,对于页式存储管理,首先需要了解两个概念:页面和页帧
页帧:又称物理页面,是指把物理空间划分为大小相同的基本分配单元,基本单元的大小为2的N次方。因此内存物理地址可以由二元组(f,o)表示,f为帧号,o为帧内偏移,假设每一帧的大小为2的s次方,那么物理地址= f*2S+o
页面:又称为逻辑页面,是指把逻辑地址空间划分为大小相同的基本分配单元。因此逻辑地址可以由二元组(p,o)表示,p为页号,o为页内偏移,假设每一页的大小为2的s次方,那么逻辑地址= p *2S + o。在linux下,可以用shell命令getconf PAGESIZE来查看页面大小。
为了方便,帧和页的基本大小相同,因此页内偏移等于帧内偏移;但页号不等于帧号。因此只需要维护页号到帧号的映射关系就行了,这就是页表的作用。
每个进程都有一个页表,每个页面对应一个页表项,页表随着程序的允许而动态变化,页表基址寄存器记录页表的基址。由页表基址加上页号就能得到相应的页表项。
CPU计算的时候取出逻辑地址(页号,偏移);用页号加上页表基址得到页表项,取出帧号;通过帧号和偏移,就找到了物理内存的实际地址。
访问一个单元需要两次内存访问(先读页表项,再度数据)。
如果地址空间比较大,而页面的基本单元比较小,那么一个页表的会很大。
3.段页式
段式存储在内存保护方面有优势,页式存储在内存利用和优化转移后备存储(虚拟存储)由优势。
段页式是二者的集合,即在段式存储管理基础上给每个段加了一级页表。这样逻辑地址就变成了三元组(s,p,o)段号 页号 页内偏移。
段页式存储管理,进程的段表项 实际上存储的是该段的页表项,这样不同段(属于不同的进程)可以指向同一个页表,共享段。
十六、CPU比较高的原因
1、首先查看是哪些进程的CPU占用率最高
ps -aux --sort -pcpu | more
定位有问题的线程:
~~~shell
ps -mp pid -o THREAD,tid,time | more
2、查看JAVA进程的每个线程的CPU占用率
ps -Lp 5798 cu | more
#5798是查出来进程PID
3、追踪线程,查看负载过高的原因,使用JDK下的一个工具
jstack 4444
jstack -j -d64 -m 4444 #4444是PID -j -d64指定为64位操作系统
4、日志中,包含某条件的行数
find access_log.20160423.txt | xargs cat | grep .*helloworld.*|wc -l
例子说明:统计含"helloworld"字符串的总行数
5、日志中,不包含某条件的行数
find access_log.20160423.txt | xargs cat | grep -v .*helloworld.*|wc -l
例子说明:统计不含"helloworld"字符串的总行数
6、查找文件夹下,查找包含某一个字符串的文件
find <directory> -type f -name "*.c" | xargs grep "<strings>"
<directory>是你要找的文件夹;如果是当前文件夹可以省略
-type f 说明,只找文件
-name "*.c" 表示只找C语言写的代码,从而避免去查binary;也可以不写,表示找所有文件
<strings>是你要找的某个字符串