操作系统是一组用于控制和管理计算机系统硬件和软件资源、合理地对各类作业进行调度,以及方便用户使用的程序集合。
操作系统是裸机之上的第一层软件,是建立其他所有软件的基础。它是整个系统的控制管理中心,既管硬件,又管软件,它为其它软件提供运行环境。
有效性,方便性,可扩充性,开放性
1.操作系统作为用户与硬件系统之间的接口。
2.操作系统作为计算机资源的管理者。
3.操作系统实现了对计算机资源的抽象。
缺点:人机速度矛盾
优点:缓解人机速度矛盾
缺点:系统资源利用率依然低
推动多道批处理形成的主要动力是:提高资源利用率和系统吞吐量
优点:多道程序并发进行,资源利用率高
缺点:不提供人机交互能力(缺少交互性)
推动分时系统形成的主要动力:满足用户需求:人机交互和共享主机
特点:多路性,独立性,及时性,交互性
优点:提供人机交互
缺点:不能优先处理紧急事务
典型系统:Multics (MIT);UNIX;Linux
关于windows系统:是分时系统和实时系统的组合,根据不同的情况来进行分时系统的操作和实时系统的操作
特点:多路性,独立性,及时性,交互性,可靠性
1.硬实时系统:必须在被控制对象规定时间内完成(火箭发射)
2.软实时系统:可以松一些(订票)
优点:可以优先处理紧急事务
从可靠性看实时操作系统更强,从交互性看分时操作系统更强
特权指令:不允许用户程序使用(只允许操作系统使用)如IO指令、置中断指令
非特权指令:普通的运算指令
内核程序:系统的管理者,可执行一切指令、运行在核心态
应用程序:普通用户程序只能执行非特权指令,运行在用户态
用户态(目态):CPU只能执行非特权指令
核心态(管态、内核态):可以执行所有指令
用户态到核心态:通过中断(是硬件完成的)
核心态到用户态:特权指令psw的标志位:0用户态 1核心态
常考谁在用户态执行,谁在核心态执行
1.处于操作系统的最底层,是最接近硬件的部分
2.这些程序的运行具有原子性,其操作只能一气呵成
3.这些程序的运行时间都较短,而且调用频繁
内中断(异常,信号来自内部)
外中断(中断,信号来自外部)
系统给程序员(应用程序)提供的唯一接口,可获得OS的服务,在用户态发生,在核心态处理
大内核
微内核
为了更好地描述和控制程序并发执行,实现操作系统的并发性和共享性(进程是动态的,程序是静态的)
动态性,并发性,独立性
是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位
在引入线程的操作系统中,线程是调度和分配的基本单位 ,进程是资源拥有的基本单位
在未引入线程的操作系统中,进程是系统进行资源分配和调度的基本单位
PCB:保存进程运行期间相关数据,是进程存在的唯一标志,常驻内存
程序段:能被进程调度到的CPU代码
数据段
状态种类
状态变化
就绪态->运行态:处于就绪态的进程被调度后,获得处理机资源(分派处理机时间片)
运行态->就绪态:系时间片用完或在可剥夺统中有更高级的进程进入
运行态->阻塞态:进程需要的某一资源还没有准备好
阻塞态->就绪态:进程等待的时间到来时
进程状态转化图:
引入目的:为了更好的使用多道程序并发执行,提高资源利用率和系统吞吐量
特点:是程序执行的最小单位,基本不拥有任何系统资源(调度的基本单位)
是对处理机进行分配,即从就绪队列中按照定的算法(公平、高效)选择一个进程并将处理机分配给他运行,以实现进程并发进行
时间片轮转 RR:剥夺 时间片的大小q很重要
按照顺序来进行就绪队列的排序,注意一点的是如果在某一时刻作业B到达,然后作业A时间片执行完毕(但是没有执行完),需要把作业A排到就绪队列队尾!!!
如果q很大,能使得每个进程都能在q时间片之内运行完,那么就退化为FCFS算法;其他情况需要画甘特图分析!!!
两个公式:
周转时间 = 结束时间 - 到达时间
带权周转时间 = 周转时间 / 运行时间
一个例题:
注意两道作业的意思:内存里最多只能同时存在两道作业,在内存里有两道作业时,此时在到达的作业只能在后备队列里储存。作业调度和进程调度好理解
算法思想:对其他调度算法的折中权衡
算法规则
1.设置多级就绪队列,各级队列优先级从高到低,时间片从小到大
2.新进程到达时先进入第1级队列,按FCFS原则排队等待被分配时间片,若用完时间片进程还未结束,则进程进入下一级队列队尾。如果此时已经是在最下级的队列,则重新放回该队列队尾
3.只有第k级队列为空时,才会为k+1级队头的进程分配时间片用于进程调度:用于作业/进程调度
是否可抢占?:抢占式的算法。在 k级队列的进程运行过程中,若更上级的队列(1~k-1级)中进入了一个新进程,则由于新进程处于优先级更高的队列中,因此新进程会抢占处理机,原来运行的进程放回k级队列队尾。(因为没运行完,所以放到k级队尾就绪等待)优缺点:
对各类型进程相对公平(FCFS的优点)﹔每个新到达的进程都可以
很快就得到响应(RR的优点)﹔
短进程只用较少的时间就可完成(SJF的优点)﹔
不必实现估计进程的运行时间(避免用户作假);
可灵活地调整对各类进程的偏好程度,比如CPU密集型进程、I/o密集型进程
(拓展:可以将因I/o而阻塞的进程重新放回原队列,这样I/o型进程就可以保持较高优先级)
是否会导致饥饿:会
例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。
P1(1)->P2(1)->P1(2)->P2(1)->P3(1)->P2(2)->P1(5)
时间0:P1进入第一队列,运行1,后进入第二队列队尾
时间1:P2到达第一队列,运行1,后进入第二队列队尾
时间2:P1运行2,后进入第三队列队尾
时间4:P2运行1s后,P3进入第一队列,P2被抢占,进入第二队列队尾
时间5:P3进入第一队列,P3运行1
时间6:P2运行2
时间8:P1运行5
协调进程之间的相互制约关系
两种:直接制约和间接制约。
引起制约的原因:这种制约可分为直接制约和间接制约,进程间的直接制约是被制约进程和制约进程之间,存在着使用对方资源的需求。
一次仅允许一个进程使用的资源**(打印机、共享缓冲区、共享变量、公共队列)**
在每个进程中访问临界资源的那段程序
原则
基本方法
信号量是被看做具有原子操作的计数器
信号量的物理意义∶
(1)信号量的值大于0︰表示当前资源可用数量【S=5 有5个可用资源】
小于0:其绝对值表示等待使用该资源的进程个数【S=-5 有5个进程在等待资源】
(2)信号量初值为非负的整数变量,代表资源数。
(3)信号量值可变,但仅能由P、V操作来改变。
相当于wait操作
(1)P操作一次,S值减1,即S=s-1(请求分配一资源)【P(s)=S-1 消耗一个资源】【S=5 P(s); S=4】
(2)如果S≥0,则该进程继续执行;
如果S<0表示无资源则该进程的状态置为阻塞态,【相当于阻塞队列】 s=0表示最后一个资源恰好被分配出去!!!
把相应的PCB连入该信号量队列的末尾,并放弃处理机,进行等待(直至另一个进程执行V (S)操作)
相当于signal操作
(1)v操作一次,s值加1,即S=S+1(释放一单位量资源)
(2)如果S>0,表示有资源,则该进程继续执行;如果S≤0,则释放信号量队列上的第一个PCB所对应的进程(阻塞态改为就绪态),执行v操作的进程继续执行。s=0表示阻塞队列里最后一个进程刚好被唤醒!!!
S1缓冲区是否空(0表示不空,1表示空),初值S1=0;
S2缓冲区是否满(0表示不满,1表示满),初值S2=0;
mutex互斥信号量,初值为1;
full满缓冲区数,初值为0;
empty空缓冲区数,初值为N;
一组生产者和一组消费者共享一个初始为空,大小为n的缓冲区,【生产者生产->消费者取 同步关系】
只有当缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待,
只有当缓冲区不空时,消费者才能从中取出消息,否则必须等待,
只允许一个生产者放入消息,或者一个消费者取出消息。【生产者的放 和 消费者的取 互斥关系】
伪代码
//这里的P代表wait(),V代表signal()
Semaphore mutex=1;//临界区信号量(互斥) 互斥信号量初始化为1!
【信号量Semaphore,实现互斥的时候mutex=1,当一个进程使用资源的时候P(mutex),mutex=0,则资源数为0,其它进程无法使用资源】
Semaphore empty=n;//空闲缓冲区为n个
Semaphore full=0;//满缓冲区数(有资源)【full=0代表没有缓冲区被充满】
producer(){
while(1){
produce an item in nextp;//生产一个东西
P(empty); //空缓冲区-1
P(mutex); //互斥的访问缓冲区,mutex=0,生产者进入了缓冲区
【这里两个P操作不能交换:若交换,则生产者占用缓冲区mutex=0,若此时缓冲区全满empty=0,则发生阻塞,生产者等待消费者消费,但消费者无法进入临界区,则死锁】
add nextp to buff; //行为 in=(in+1)%n;
V(mutex); //离开缓冲区
V(full); //提供了资源
}
}
consumer(){
while(1){
P(full); //看看缓冲区是不是有资源的,有则-1
P(mutex); //进入临界区
【不能对调,对调死锁】
remove an item from buffer; // out=(out+1)%n;
V(mutex); //释放临界区
V(empty); //空缓冲区+1
}
}
非剥夺资源的竞争和进程的不恰当推进顺序(与饥饿的区别:饥饿为缺乏某些资源的进程)
通常系统中拥有的不可剥夺资源,其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局,如磁带机、打印机等。
只有对不可剥夺资源的竞争才可能产生死锁,对可剥夺资源的竞争是不会引起死锁的。
【P1有资源A,需要资源B,且不会释放资源A; P2有资源B,需要资源A,且不会释放资源B; 死锁】
【P1需要A资源4个 P2需要A资源4个 A资源只有6个,且A资源为不可剥夺资源 P1申请了3个,P2申请了3个,P1P2都在申请,但没有了】
进程在运行过程中,请求和释放资源的顺序不当,也同样会导致死锁。
例如,并发进程P1、P2分别保持了资源R1、R2,而进程P1申请资源R2,进程P2申请资源R1时,两者都会因为所需资源被占用而阻塞。
【P1申请R1,R2,后结束释放资源,P2再申请R1、R2,则无阻塞】
互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。(这个是一定要有的,不管会不会产生死锁,这个条件都必须存在)
非剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)
请求和保持条件︰进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。(请求别的资源但是保持自己的资源不放手)
循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。
【P1->P2->P3->P4->P1:P1等P2的资源,2等3,3等4,4等1】
当死锁产生的时候一定会有这四个条件,有一个条件不成立都不会造成死锁。其中互斥使用资源是无法破坏的
多个进程因竞争资源而造成的一种僵局,如果没有外力,这些进程将无法推进
解决死锁的三种方法:死锁的预防、避免、检测与恢复。
1.死锁预防的基本思想:打破产生死锁的四个必要条件的一个或几个。【主动出击】
2**.避免死锁**的策略︰在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而避免死锁。【躲着它】
3.死锁的检测及解除【一开始不作为,然后一步到位:不预防避免死锁,有死锁再解除】
无需采取任何限制性措施,允许进程在运行过程中发生死锁。通过系统的检测机构及时地检测出死锁的发生,然后采取某种措施解除死锁。
如果允许系统资源都能共享使用,则系统不会进入死锁状态。
但有些资源根本不能同时访问,如打印机等临界资源只能互斥使用。
所以,破坏互斥条件而预防死锁的方法不太可行,而且在有的场合应该保护这种互斥性。
当一个已保持了某些不可剥夺资源的进程,请求新的资源而得不到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。
这意味着,一个进程已占有的资源会被暂时释放,或者说是被剥夺了,或从而破坏了不可剥夺条件。
【P1有3个A资源,请求3个B资源,B资源没有,则释放3个A资源】
采用预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行。
一旦投入运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就可以保证系统不会发生死锁。
【P1 需要A3 B4 C5 ,现在P1有A2 B3 C0 ,申请A1 申请B1 申请C5,全部申请完就允许】
这种方式实现简单,但缺点也显而易见,系统资源被严重浪费,其中有些资源可能仅在运行初期或运行快结束时才使用,甚至根本不使用。
而且还会导致**“饥饿”现象,当由于个别资源长期被其他进程占用时,将致使等待该资源的进程迟迟不能开始运行。**
【P1过程 T1只需要A资源 T2 需要B T3需要C 后结束,但在T1时刻有ABC资源,造成浪费】
对第一种协议的改进,允许一个进程只获得运行初期所需要的资源后,便开始运行。在运行过程中逐步释放自己的,且已经用毕的全部资源,然后再请求新的所需资源。
可以使进程更快的完成任务,提高设备的利用率,还可以减少进程发生饥饿的概率。
为了破坏循环等待条件,可采用顺序资源分配法。首先给系统中的资源编号规定每个进程,规定每个进程必须按编号递增的顺序请求资源,同类资源一次申请完。
也就是说,只要进程提出申请分配资源Ri,就必须把Ri以下的编号全部申请到才能运行(导致资源的浪费),则该进程在以后的资源申请中,只能申请编号大于Ri的资源。
银行家算法是最著名的死锁避免算法。
它提出的思想是:把操作系统看做是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
操作系统按照银行家制定的规则为进程分配资源,
当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。
【max>available,申请量大于可申请,则推迟】
当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过了该进程对资源的最大需求量
【max>available,申请量之和大于可申请,则推迟】
若超过则拒绝分配资源,
若没有超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,
若能满足则按当前的申请量分配资源,
否则也要推迟分配。
可利用资源矢量Available:含有m个元素的歉组,其中的每一个元素代表一类可用的资源数目。Available[j]=K,则表示系统中现有Rj类资源K
最大需求矩阵Max:为n*m矩阵,定义了系统中n个进程中的每一个进程对m类资源的最大需求。Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
分配矩阵Allocation:为n*m矩阵,定义了系统中每一类资源当前已分配给每一进程的资源数。AlloCation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
需求矩阵Need:为n*m矩阵,表示每个进程尚需的各类资源数Need[i,j]=K,则表示进程i还需要Rj类资源的数目为K。
Need[i,j]=Max[i,j]-Allocation[i,j]
设Requesti是进程Pi的请求矢量,如果Requesti[j]K,表示进程Pi需要Rj类资源K个。当Pi发出资源请求后,系统按下述步骤进行检查:
①如果Requesti[j]<=Need[i,j],便转向步骤②;否则认为出错
因为它所需要的资源数已超过它所宣布的最大值。
②如果Requesti[ij]<=Available[i],便转向步骤③;否则,表示尚无足够资源,Pi须等待。
③系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
1.Available[j]=Available[i]- Requesti[j];
2.Allocation[i,j]= Allocation[i,j]+ Requesti[ j];
3.Need[i,j] = Need[i,j] - Requesti[j];
④系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。
若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
一个四道作业的操作系统中,设在一段时间内先后到达6个作业,它们的提交时间和运行时间见表
系统采用短作业优先的调度算法,作业被调度进运行后不再退出【非抢占式】,但当一作业进入运行时,可以调整运行的优先次序。
1按照所选择的调度算法,请分别给出上述6个作业的执行时间次序
次序156342
JOB1提交到完成为9:00,JOB2-6已经全部提交,**短作业优先:**则选择时间短到长的进行排序56342
标准答案
标准的运行流程如下
2计算在上述调度算法下作业的平均周转时间
周转时间T=作业完成时间-作业的提交时间
平均周转时间=1/n(T1+T2+…Tn)
n为作业进程数,本题为6
标准答案
T1=60
T2=135
…
T6=35
平均周转时间=1/6*(60+135+70+90+30+35)=70
一个具有两道作业的批处理系统【进程只允许在内存中存在两个】,
作业调度【从外存向内存里面调度】采用短作业优先的调度算法,
进程调度【分配处理机cpu】采用以优先数为基础的抢占式调度算法,如下表的作业序列
(表中所有作业优先数即为进程优先数,数值越小优先级越高)。
1.列出所有作业进入内存时间及结束时间
作业ABCD都在外存,可以向内存中调入两个作业,按优先数进入CPU
到达时间
10:00 A到达 进入内存 CPU运行
10:20 B到达 进入内存 内存中有AB A运行20min,剩余20min B优先数高,B开始运行
10:30 C到达,A剩余20min,B运行10min,剩余20min 由于采用短作业优先算法,50>20=20,所以C不被调入内存
10:50 D到达,B作业完,下处理机,下内存 由于采用短作业优先算法,C50min,D20min,D进入内存 内存有AD,进程调度A优先数高,A进CPU
11:10 A结束 C进内存,内存有CD,C优先数高,先进处理器
12:00 C结束,D进处理器
12:20 D结束
标准答案
1、10:00,A作业到达,进入系统开始运行。
2、10∶20,B作业到达,系统内存中只有一道作业A,B作业进入内存,此时A运行20min,还剩20min,由于B作业的优先数小,即优先级高,则作业A进入就绪状态,作业B开始运行。
3、10∶30,C作业到达,内存中已有两道作业,则在后备队列中等待被作业调度程序调度,A等待10min,剩20min,继续等待,B运行10min,还剩20min,继续运行。
4、10∶50,D作业到达,B作业完成,内存中只剩下作业A,剩20min,作业D与作业C相比,作业D的运行所需时间少被调到进内存,内存中的A和D相比,A的优先级高,A继续运行。
5、11∶10,作业A运行完成,作业C被调度进内存,内存中有作业D和作业C,C的优先级比D高,C先运行。
6、12: 00,作业C完成,D运行。
7、12∶20,作业D完成
2.计算平均周转时间
各作业执行时间的周转时间为
作业A 70分钟
作业B30分钟
作业C 90分钟
作业D 90分钟
作业的平均周转时间为T=70 (min)
它们的优先数分别为1,2,3,4,5(1为最低优先级),
对下面的每种调度算法,分别计算作业的平均周转时间。
1最高优先级先
2时间片轮转(时间片为2分钟)
3 FIFO( FCFS ) (作业到达顺序为C、D、B、E、A)
4短作业优先
【题目没提:默认为非剥夺式】
1对最高优先级优先算法
平均周转时间=(10+18+24+28+30)/5=22分钟
2对时间片轮转算法
平均周转时间=(2+12+20+26+30)/5=18
3 FIFO (作业到达顺序为C、D、B、E、A)
平均周转时间=(6+14+18+28+30)/5=19.2
4短作业优先
A:2 B:4 C:6 D:8 E:10
平均周转时间=(2+6+12+20+30)/5=14
【已分配Allocation 尚需need 未分配available Max=已分配+尚需=Allocation+Need 后available=原available+Allocation】
⑴该状态是安全的吗?【假设P0->P1->P2->P3->P4可以执行结束,我能够找到一个安全序列,则该状态是安全的】
未分配2431,可以给P0用,P1不行,P2不行,P3不行,P4不行,所以先运行P0,运行结束未分配为2441
未分配2441,P1不行,P2不行,P3行,P4不行,运行P3,结束未分配为2572
未分配2572,P1不行,P2不行,P4行,运行P4,结束未分配为2586
未分配2586,P1不行,P2行,运行P2,结束未分配为3 8 13 10
未分配3 8 13 10,P1行,运行P1
所以安全序列为P0->P3->P4->P2->P1
标准答案
P0(2 4 4 1)->P3(2572)->P4(2 5 8 6)->P2(3 8 13 10)->P1(4 8 13 10)为其中一个安全序列,所以该状态安全。
⑵如果P1再提出资源请求Request (0 3 2 1),系统能否将资源分配给它?【找不到安全序列,系统处于危险状态,不能分配】
标准答案
因为一旦分配,P1还需P1(0 4 3 0),系统的可用资源数为(2 1 1 1),
在所有进程中只有P0(2 0 1 0),为其分配,作上完成标志,可用资源为(2 1 2 1);
而P1/P2/P3/P4均不能作上完成标志
更好的支持多道程序的并发执行,提高系统性能
保证各道作业在各自的存储空间内运行,互不干扰。
在多道程序环境下,程序中的逻辑地址与内存中的物理地址不可能一致,因此存储管理必须提供地址变换功能,把逻辑地址转换成相应的物理地址
利用虚拟存储技术或自动覆盖技术,从逻辑上扩充内存。
创建源文件
由编译程序将用户源代码编译成若干目标模块,生成目标文件
由链接程序将编译后形成的一组目标模块及所需的库函数链接在一起, 形成一个完整的装入模块。生成可执行文件(形成逻辑地址)
由装入程序将装入模块装入内存运行。
得到结果
重定位:装入内存时,相对地址(数据、指令地址)要作出相应的修改以得到正确的物理地址,这个修改的过程称为重定位。
系统分为系统区和用户区,应用程序装载到用户区,内存中仅驻留一道用户程序,整个用户区为用户一个人所占,使用用户区的全部空间
分配到内存固定的区域(有内部碎片):分配给进程的内存有一部分没有用上
例如:30mb分30mb
将内存用户空间划**分为若干个固定大小(每块的大小不一定相同)**的区域,每个区域称为一个分区,在每个分区中只装入一道作业 ,从而支持多道程序并发设计
分配到内存不同的固定区域,分区可以相等可以不等(内部碎片,内零头)
例如:30mb分为10mb和20mb
按照程序的需要进行动态的划分
空闲分区以地址递增的次序链接。分配内存时顺序查找,找到大小能满足要求的第一个空闲分区。(增加查找开销)
例如:从0x0001到0xFFFF顺序查找,30mb小了,20mb小了,40mb合适就你了
空闲分区按容量递增的方式形成分区链,找到一个最接近目标大小的满足要求的空闲分区。(外部碎片过多)
例如:从1mb到9999mb查找,1mb小了,2mb小了,3mb合适
外部碎片:因为碎片过小而无法利用,例如30mb的空闲分区,进程需要29.999mb,剩下的0.001mb为外部碎片
空闲分区以容量递减的次序链接。找到第一个能满足要求的空闲分区,即挑选出最大的分区。(对大进程不利)
例如:空闲分区有100mb,70mb,…,1mb
70mb进程来了进100mb的空闲分区,然后100mb进程来了就要等等等
由首次适应算法演变而成。不同之处是,分配内存时从上次查找结束的位置开始继续查找。
例如:第一次找到了0xFF00,第二次从0xFF00开始找
将内存中的所有作业进行移动,使它们全都相邻接,把原来分散的多个小分区合成一个大分区
离散分配:程序在内存中的存放不一定是连续的
离散的基础:
内存可以装入程序一页;连续的多个页不一定装入连续的多个块当中;系统的页块大小是不变的
优点:没有外零头,但是存在内零头
逻辑地址到物理地址的转换:由地址变换机构完成
逻辑地址:由页号和页内偏移量组成
页号到物理块号的转换:由页表完成
每个存储块的大小和页面的大小相同
有两种地址变换结构:
两级和多级页表
对换操作
外存可以分为文件区和对换区:文件区存放文件,侧重于提高存储空间利用率,应用离散分配方式;对换区存放从内存中进进出出的文件,交换较频繁,侧重于对换这个操作,应用连续分配方式
换出换入:
分页系统地址变换机构图:(牢记!!!)
具有快表的情况
引入分段式的原因:
分段制造了二维空间,而内存是一维的
段表
地址变换机构:
分页和分段的联系(信息共享)
1.相同点:
2.不同点:
段式存储在内存保护和共享方面有优势,页式存储在内存利用和优化转移到后备存储方面有优势。
该图中仍然存在未写满的页,说明仍然存在内零头的问题
如下管理:
访问:第一次段表,第二次页表,第三次数据,一共访问三次内存
可以从物理和逻辑上增加
一次性和驻留性严重降低内存利用率,减少系统吞吐量。
针对同一程序,当一个程序的大小超过内存的大小的时候,不能一次性把作业全部装入内存运行,这个时候将程序分段,分为必须一直在内存的段和不是必须的段,当非必须的段用不到的时候将其调出内存,把需要的段覆盖进来,这样就可以实现这个程序的运行了。解决了一次性问题
操作系统自动把暂时不能执行的程序保存到外存中;解决了驻留性问题
例如:在打大型游戏时候,将QQ微信放到外存
在有限容量的内存当中,自动装入更多更大的内存
特征(多次性和对换性就是一次性和驻留性 反过来)
实现虚拟存储的关键技术
请求分页技术
请求分段技术
抖动
选择的页面不恰当可能导致频繁的内存频繁的换进换出,吞吐量很低
在逻辑上扩充内存
引入算法:
页表
最小物理块:
一般来说,增加物理块的个数应该是可以减少缺页中断的次数的,但是这种说法不能绝对化了,比如FIFO就有可能出现问题,异常现象!
注意:页面淘汰是由缺页中断引起的,但缺页中断不见得一定引起页面淘汰
总是选择作业中驻留时间最长(即最老)的一页淘汰。即:先进入主存的页面先退出主存。淘汰最先进入内存的页面(3个内存块都为空,3次缺页中断)
注:对于FIFO页面淘汰算法,有时增加分配给作业的可用 内存块数,它的缺页次数反而上升,通常称为异常现象
总是把最长时间未被访问过的页面淘汰出去(需要寄存器和栈)。认为过去一段时间里不曾被访问过的页面,在最近的将来可能也不会再被访问。
淘汰到目前为止访问次数最少的页面
把以后不再使用的或最长时间内不会用到的页面淘汰出去(理论上,不会实现,因为我们不知道未来页面的访问顺序是什么)
给每个页面设置一个访问位(比如R),在最近一段时间内中在未访问也就是访问位为0的页面上任选一页进行淘汰
除了考虑一个页面最近有没有被访问过之外,操作系统还应考虑页面有没有被修改过。在其他条件都相同时,应优先淘汰没有修改过的页面,避免I/O操作。这就是改进型的时钟置换算法的思想。
为方便讨论,用**(访问位,修改位)**的形式表示各页面状态。如(1,1)表示一个页面近期被访问过,且被修改过。
页面频繁的换进换出
原因:分配给进程的进程块不足 ; 选择的页和段不合适
固定分区局部置换(物理块不变)
给进程分配3个物理块,不变
可变分配局部置换 (动态增加物理块)
给进程分配3个物理块,缺页,加一块
可变分配全局置换(只允许从该进程的内存页面中挑选一页)
解:OPT最佳置换算法︰淘汰最远将来才使用的页。
2,3,1,2,4【引起缺页,要换123之中的一个】,3【3最近要使用】,5 , 7,2【2最近要使用】,3,4,3,6,2,1【1最远使用,所以淘汰1】,3,4,1
FIFO先进先出置换算法:淘汰最先进来的页。
2【最先进来,最先淘汰2】,3,1,2,4【引起缺页,要换123之中的一个】,3,5 , 7,2,3,4,3,6,2,1,3,4,1
LRU最近最久未使用置换算法:最近最久未使用的页。
2,3【因为2更新,所以3为最久未使用,所以淘汰3】,1,2【2更新】,4【引起缺页,要换123之中的一个】,3,5 , 7,2,3,4,3,6,2,1,3,4,1
总体目标是高效性和通用性,也就是为了使用方便、与设备无关、效率高、管理统一。
I/O系统:用于实现数据输入、输出及数据存储的系统
功能:接受CPU命令,控制I/O设备工作,解放CPU
可分为控制块设备的控制器和控制字符设备的控制器
CPU需不惜花代价查询I/O状态
这种方式也可以称为查询方式,cpu不断地去查询设备控制器是否将数据放到了数据存储器中,或者从数据存储器存到设备中,当完成IO时cpu才能去干别的事。CPU浪费资源的情况非常大
这种方式当cpu发出指令后就可以去干别的事,当设备控制器把数据存在数据存储器后,向cpu发出中断请求,然后cpu再来处理这部分数据。但是即使如此,还是一个一个字或者字节传输,效率太低了
虽然中断方式提高了cpu的利用率,但是数据寄存器有限,中断是以字节单位进行中断,也就是说读取或存储一个字节后就需要进行中断,那么其实cpu的利用率还是很低的,所以就诞生了DMA方式,这种方式由DMA控制器直接将设备中的数据以数据块为单位直接传输到内存中,当传输结束后才向cpu发起中断。
DMA虽然大大地提升了cpu的利用率,但是DMA只能传输一个连续的数据块。所以引入了IO通道的控制方式,IO通道控制方式可以传输不连续的数据块,减少了cpu干预。cpu通过对IO通道发出指令,然后让IO通道自己工作,等数据传输完才向cpu发起中断。
设备独立性软件的功能
设备的固有属性:独占性;(临界资源)共享性;可虚拟性;所以因此也有三种属性的设备:独占设备,共享设备和虚拟设备
\1) 单缓冲:当数据到达率与离去率相差很大时,可采用单缓冲方式。
\2) 双缓冲:**当信息输入和输出率相同(或相差 不大)**时,可利用双缓冲区,实现两者的并行。【非空不能放东西,非满不能取东西】
\3) 多缓冲:对于阵发性的输入、输出,为了解决速度不匹配问题,可以设立多个缓冲区。
循环缓冲区:分为三个队列:空缓冲队列,输入队列:装满输入数据的缓冲队列,输出队列:装满输出数据的缓冲队列
四个缓冲区:收容输入数据的工作缓冲区,提取输入数据的工作缓冲区,收容输出数据的工作缓冲区,提取输出数据的工作缓冲区
\1) 独占设备:
不能共享的设备,即:在一段时间内,该设备只允许一个进程独占。如打印机。
\2) 共享设备:
可由若干个进程同时共享的设备。如磁盘机。
\3) 虚拟设备:
是利用某种技术把独占设备改造成可由多个进程共享的设备。
\1) 独占分配技术:
是把独占设备固定地分配给一个进程,直至该进程完成I/O操作并释放它为止。
\2) 共享分配技术:
通常适用于高速、大容量的直接存取存储设备。由多个进程共享一台设备,每个进程只用其中的一部分。
\3) 虚拟分配技术:
利用共享设备去模拟独占设备,从而使独占设备成为可共享的、快速I/O的设备。实现虚拟分配的最有名的技术是SPOOLing技术,也称作假脱机操作。*(虚拟化技术到处都是欺骗)
【分配技术应该考虑:固有性质、分配算法、安全性、独立性【应用程序独立于具体使用的物理设备】
什么是设备独立性
设备独立性是指操作系统把所有外部设备统一当作成文件来看待,只要安装它们的驱动程序,任何用户都可以象使用文件一样,操纵、使用这些设备,而不必知道它们的具体存在形式。
为什么要引入设备独立性
引入设备独立性后可以调高设备的利用率和分配时的灵活性;提高系统的可适应性和可扩展性;可以方便用户操作,易于实现IO重定向
如何实现设备独立性
为了实现设备的独立性,应引入逻辑设备和物理设备两个概念。在应用程序中,使用逻辑设备名称来请求使用某类设备;而系统执行时,是使用物理设备名称。鉴于驱动程序是一个与硬件(或设备)紧密相关的软件,必须在驱动程序上设置一层软件,称为设备独立性软件,以执行所有设备的公有操作、完成逻辑设备名到物理设备名的转换(为此应设置一张逻辑设备表)并向用户层(或文件层)软件提供统一接口,从而实现设备的独立性
柱面号、盘面号、扇面号
通常磁盘数据访问时间计算分为三个部分(实际上是四个,但是启动时间不加说明时忽略不计):
当设备无访问请求时,磁头不动;当有访问请求时,磁头按一个方向移动,在移动过程中对遇到的访问请求进行服务,然后判断该方向上是否还有访问请求,如果有则继续扫描;否则改变移动方向,并为经过的访问请求服务,如此反复
总是向一个方向移动,例如自里向外移动。移动臂到达最后个一个柱面后,立即带动读写磁头快速返回到最里的欲访问磁道。返回时不为任何的等待访问者服务。返回后可再次进行扫描
题11.假设系统中磁头当前的位置在110号磁道上,
设有若干个进程先后提出磁盘I/O请求序列为65,68,49,28,100,170,160,48和194。
(1)按FCFS算法进行调度的平均寻道距离;
解:(1)平均寻道距离55.3条磁道
110->65->68->49->28->100->170->160->48->194
(2)按SSTF算法进行调度的平均寻道距离;
110->100->68->65->49->48->28->160->170->194
(3)按SCAN算法进行调度的平均寻道距离;【题目没给最外侧磁道数目,则扫描到题目给出的最大数目194,若给了例如200,则要扫描到200】
110->160->170->194->100->68->65->49->48->28
(4)按循环SCAN算法进行调度的平均寻道距离;
110->160->170->194->28->48->49->65->68->100
文件是以计算机硬盘为载体的存储在计算机上的信息集合
文件系统:就是操作系统中负责操纵和管理文件的一整套设施,它实现文件的共享和保护,方便用户按名存取(*基本目标*),提高文件的存取速度(*最重要目标*)。
文件管理、目录管理、文件空间管理、文件共享和保护、提供方便的接口。
从逻辑组织的角度看,文件由若干记录构成
从物理组织的角度看,文件由若干数据块组成
例如文本框中打字
磁带上的文件一定是顺序文件
在文件系统内部给每个文件唯一地设置一个文件控制块,它用于描述和控制文件的数据结构,与文件一一对应
类似进程的PCB
在不同的 UFD 中,可以使用相同的文件名
不同用户可以使用不同的文件名访问系统中的同一个共享文件
三级或者三级以上的称作树形目录
多层目录的优缺点
线性查询和哈希查询
在一个系统中仅采用一种方法来为文件分配外存空间;在采用不同的分配方式的时候,将形成不同的文件物理结构
1.连续分配(有外部碎片):为每一个文件分配一组相邻接的盘块
2.链接分配(解决了外部碎片,但是不支持直接访问,数据易丢失):可以将文件装到多个离散的盘块中采用链接分配方式时,可通过在每个盘块上的链接指针,将同属于一个文件的多个离散的盘块链接成一个链表,把这样形成的物理文件称为链接文件
3.索引分配(加入 文件分配表FAT 可直接访问,减少了访问磁盘的次数):不支持高效的直接存取,FAT需要占用较大的内存空间
FAT表例题:
单级索引分配
两级索引分配
混合索引分配
4.成组链接:成组链接法是结合了空闲表和空闲链表法的,UNIX系统采用的就是成组链接法。成组链接法中保存的是当前可用的存储盘块的地址。
1)空闲表法(连续分配方式)
2)空闲链表法
分为空闲盘块和空闲盘区
注意盘区在盘块的基础上是几个连续的空白盘块合并在一起
3)位示图法
盘块号 = 字号 * n(代表字长) + 位号;里面1代表已分配,0代表未分配
主要能根据题目给的图推导出盘块号,字号,位号和字长的关系,因为有时候不一定位号是从0开始的
4)成组链接法
图中的例子:空间1-4存储的是可用的一个盘块的地址,然后这些盘块就是单级索引,指向的位置就是存储位置;空间0的盘块1地址指向的是盘块1,但是盘块1页是存储索引的,这就是二级索引,如果再往下走就是更高级的索引了
现在有5个数据要存储,前四个很容易可以找到单级索引进行存储,每存储一个就需要把free盘块进行修改,空间置空和空闲盘块进行修改
存到第五个的时候由于1号盘块往下走还有高级索引,所以不能直接存储
这时候需要把盘块1指向的内容填进盘块0中,就是现在这样,然后再继续按照刚才的样子分配就可以了
至于回收
系统释放data_5数据段,释放盘块1,将盘块1放到可用表中,但是这时候盘块0满了,怎么办呢?
把盘块0现在的内容复制到盘块1中,然后把盘块1写入空白的盘块0中
echo "helloworld" //在屏幕上输出 helloworld
单行注释以 # 开头
# 这是一个注释
# author:ohuohuoo
# date:`date`
shell编程中,定义变量是直接定义的,没有明确的数据类型,shell允许用户建立变量存储数据,但是认为赋给变量的值都解释为一串字符
cout=1 # 定义变量
name="ohuohuo" # 定义变量
echo $cout # 取变量值
echo $name # 取变量值
shell中,英文符号"$"
用于取变量值!!
注意:
如果在变量中使用系统命令,需要加上 " `"符号(ESC键下方),如下所示
DATE1=`date`
DATE2=$(date)
使用变量的时,用英文符号"$"
取变量值,对于较长的变量名,建议加上{ }
花括号,帮助解释器识别变量的边界,如下
name="test_name"
echo "My name is ${name}and you"
shell中的变量,默认为可读可写类型,如果想要其只可读,如同url一样,需要将其声明为**只读类型变量(**如同const
),使用readonly
命令,如下脚本
Url="http://www.baidu.com"
readonly Url
Url="http://www.csnd.net"
如果想要删除变量,使用unset
命令解除命令赋值,但是unset
不能删除可读变量,如下所示
name="ohuohuo"
Url="http://www.baidu.com"
readonly Url # 设置可读变量
unset name # 可以被删除
unset Url # 不可被删除
echo $name # 不被打印出
echo $Url # 打印出
最好使用双引号
shell规定单引号禁止变量替换, 元字符$和*等保持其符号本身; 而双引号允许元字符变量替换.
反撇号中的字符串代表命令名
name="ohouhuoo"
str="please input your \"$name"\"
echo -e $str
花括号将变量名和后面的字符串区分开
获取字符串长度:在对变量进行取值时,使用**" # "**符号对字符串进行取值
string="abcd"
echo ${#string} # 输出 4
提取子字符串:使用字符串的截取命令,用于提取部分字符串
string="this is a test"
echo ${string:2:6} # 表示从下标为2开始截取,到下标为6截止,两端包含!!!
查找字符串:用于查找字符的位置,输出结果为字符在字符串中所占的数据位置,如果查找多个字符,那哪个字母先出现就计算哪个,如下查找it
中i
和t
两个字符,t
先出现,输出为1
string="this is a test"
echo `expr index "$string" it` # 输出 1
shell数组只支持一维数组!!!
在 Shell 中,用括号()
来定义表示数组,数组中元素用"空格"符号分割开。定义数组的一般形式为:
# 一般定义
array_name=(value1 value2 value3 value4)
# 多级定义
array_test=(
value1
value2
value3
value4
)
#
array_text[0]=value0
array_text[1]=value1
array_text[3]=value3
...
...
和读取变量名相同,使用$
符号,需要加上下标名
valuen=${array_name[n]}
echo ${array_name[@]} # 读取所有
这里获得长度注意对于数字而言,在shell中认为是一个字符串!!!
# 取得数组元素的个数
length=${#array_name[@]} # 从头到尾取
# 或者
length=${#array_name[*]} # 取所有
# 取得数组单个元素的长度
lengthn=${#array_name[n]} # 取特定
echo "传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
可以这么执行,注意可能需要赋予权限
chmod +x test.sh
./test.sh 1 2 3
举例如下:
echo "传递参数实例!";
echo "第一个参数为:$1";
echo "参数个数为:$#";
echo "传递的参数作为一个字符串显示:$*";
与其他编程语言相同的是,shell同样支持多种运算符:
shell想要使用这些运算符,需要结合其他命令和工具来使用(因为shell中不支持简单的数学运算),如使用算符运算符就需要搭配的常用的工具有两种
运算规则注意点:
a=10
b=20
sum=`expr $a + $b`
echo "两数之和为:$sum"
mul=`expr $a \* $b`
echo "两数之和为:$mul"
注意:
在windows系统中乘号(*)前边必须加反斜杠( \ )才能实现乘法运算;
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
注意:运算符和数之间必须要用空格隔开
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
a="abc"
b="efg"
if [ $a != $b ]
then
echo "$a != $b : a 等于 b"
else
echo "$a != $b: a 不等于 b"
fi
file="operator.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
echo命令在shell中用于字符串的输出,调用的格式:
echo string
echo命令还可显示复杂的输出格式
echo "helloworld"
echo "\this is a test\"
name="ohuohuo"
echo "you name is $name"
echo -e "Right!\n " # -e 表示开启转义
echo "this is other line"
echo `date`