进程、线程概念
进程:一个进程就是一个正在执行的程序的实例。
进程转换:
进程3个状态:运行态,阻塞态,就绪态。
1.进程为等待输入而阻塞。
2.调度程序选择另一个进程。
3.调度程序选择这个进程。
4.出现有效输入。
线程:轻量级进程。
作业调度:按照某种原则,从后备作业队列中选取作业进入内存,并为作业做好运行前的准备工作以及作业完成后的善后处理工作。
主要调度算法:
First Come First Serve (FCFS)先来先服务:按到达时间先后排序。
Shorted Job First (nonpreemptive & preemptive ) 最短作业优先:按作业的运行时间排序,由短到长。
Round robin 轮转调度:每个进程执行一个时间片后移到队列末尾,把CPU交给下一个进程。
Priority Scheduling (nonpreemptive & preemptive ) 优先级调度:执行当前实时优先级最高的进程。动态优先级是在创建进程时赋予该进程一个初始优先级,然后其优先级随着进程的执行情况的变化而改变。
Multiple Queues 多级队列:
1.进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待。
2.首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次优先级队列中的进程。
3.对于同一个队列中的各个进程,按照时间片轮转法调度。
4.在低优先级的队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU马上分配给新到达的作业(抢占式)。
多级队列算法运作过程示例:
用户空间建立的线程包和内核建立的线程包区别图
临界区:每个进程中访问临界资源的那段代码称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
信号量:在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。
信号量有两种操作:down,up,也就是所谓的P,V操作
down:如果信号量大于0,则继续,等于0则进程将睡眠,将信号量减1。
up:将信号量加1,如果信号量大于0,则继续,若小于或等于0,则唤醒一阻塞在该信号量上的进程。
例如:Semaphore的初值为n, m个进程使用该semaphore访问关键区,那么semaphore值的变化范围是多少?
每个进程进入关键区时都会使Semaphore减1,离开时又使Semaphore加1,所以范围是n-m到n。
信号量可以用来解决一些进程同步的问题,例如:
用P、V操作说明互斥量,定出司机与售票员之间的同步算法,司机与售票员活动如下图所示。
在汽车行驶过程中,司机活动与售票员活动之间的同步关系为:售票员关车门后向司机发开车信号,司机接到开车信号后启动车辆,在汽车正常行驶过程中售票员售票,到站时司机停车,售票员在车停后开车门让乘客下车。因此司机启动车辆的动作必须与售票员关车门的动作取得同步;售票员开车门的动作也必须与司机停车取得同步。
所以在本题中,应设置两个信号量s1、s2,s1表示是否允许司机启动汽车,其初值为0;s2表示是否允许售票员开车门,其初值为0。
所以解答为:(可以将P操作看成是wait--等待信号,V操作看成是signal--发出信号)
Semaphore s1,s2=0;
Driver() Saler()
{ {
while(true) while(true)
{ {
p(s1); 关车门;
启动车辆; v(s1);
正常行车; 售票;
到站停车; p(s2);
v(s2); 开车门;
} 上下乘客;
} }
}
几个利用信号量和线程解决的IPC(进程间通信)经典问题:
1.生产者与消费者问题
在同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
C解决此问题的源码:
1 #define N 100 //缓冲区的槽数目 2 typedef int semaphore; 3 semaphore mutex = 1 ; //临界区(缓冲区)信号量,以互斥各线程的进入 4 semaphore empty = N; //缓冲区的空槽数目 5 semaphore full = 0; //缓冲区的满槽数目 6 void producer(void) 7 { 8 int item; 9 while (TRUE) { 10 item = produce_item( ); 11 down( &empty); //空槽减1 12 down( &mutex); //进入临界区 13 inserUtem(item); //加入数据 14 up( &mutex); //离开临界区 15 up( &full); //满槽加1 16 } 17 } 18 void consumer(void) 19 { 20 int item; 21 while (TRUE) { 22 down( &full); 23 down( &mutex); 24 item = remove_ item( ); 25 up( &mutex); 26 up( &empty); 27 consume_item(item); //消费一个数据项 28 } 29 }
2.哲学家就餐问题
假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。
C解决此问题源码:
PS:philosopher函数未完整,应该修改为下图:
值得注意的是,philosopher函数会有不同的5个进程来调,参数为 0 到 N-1 。
3.读者写者的问题
有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。以下假设共享数据区是文件。这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。这些条件具体来说就是:
(1)任意多的读进程可以同时读这个文件;
(2)一次只允许一个写进程往文件中写;
(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;
(4)写进程执行写操作前,应让已有的写者或读者全部退出。这说明当有读者在读文件时不允许写者写文件。
C语言解决此问题源码:写者优先算法
死锁
资源死锁的4个条件:
现在有5个进程A、B、C、D、E,有4种类型的资源R1、R2、R3、R4。在T0时刻系统状态如下。R1、R2、R3、R4的剩余资源数依次为3、3、0、3。
回答下面问题:
(1)T0时刻是否为安全状态?
(2)若这时D提出申请(1,2,0,3),是否能实施资源分配?
虚地址到实地址的翻译过程
几种主要的页面置换算法:
FIFO(First In First Out)先进先出:按照先进先出顺序淘汰页面。(ps:页面替换时,出现重复页面,此页面的顺序按照之前的页面顺序算)
LRU( Least Recently Used ) 最近最少使用:将前一段时间内没使用的页面置换。
OPT( Optimal )最佳页面置换算法:
磁盘调度算法
FCFS (First Come First Served) 先来先服务:和进程调度一样。
最短寻道优先算法(Shortest Seek First):以磁头位置寻找下一个距离最近的磁道。
SCAN(扫描算法 又称 电梯算法):第一个磁道选择离磁头最近的磁道,然后按照磁头移动方向依次选择最近磁道,当此方向上磁道都选择完毕时,反向选择最近磁道。
例如:
Inode
文件A和文件B的inode号码虽然不一样,但是文件A的内容是文件B的路径。读取文件A时,系统会自动将访问者导向文件B。因此,无论打开哪一个文件,最终读取的都是文件B。这时,文件A就称为文件B的"软链接"(soft link)或者"符号链接"(symbolic link)。
这意味着,文件A依赖于文件B而存在,如果删除了文件B,打开文件A就会报错:"No such file or directory"。这是软链接与硬链接最大的不同:文件A指向文件B的文件名,而不是文件B的inode号码,文件B的inode"链接数"不会因此发生变化。
一个分区分成同等大小的簇,也就是连续空间的小块。簇的大小随着FAT文件系统的类型以及分区大小而不同,典型的簇大小介于2KB到32KB之间。每个文件根据它的大小可能占有一个或者多个簇;这样,一个文件就由这些这些(称为单链表)簇链所表示。然而,这些链并不一定一个接着一个在磁盘上存储,它们经常是在整个数据区域零散的储存。
文件分配表(FAT)是映射到分区每个簇的条目列表。每个条目记录下面五种信息中的一种:
1.链中下一个簇的地址
2.一个特殊的文件结束符(EOF)
3.符号指示链的结束
4.一个特殊的符号标示坏簇
5.一个特殊的符号标示保留簇 ( 0来表示空闲簇 )
Memory mapped I/O : 就是把磁盘上的file映射到内存上,当我们从内存上fetch byte时,对应的file就被读取。同样的,当我们在内存上存储字节的时候,对应的file就被写入。这就让我们不需通过read和write系统调用而去操作I/O。