一、为什么操作系统要多进程并发执行?
原因在于CPU处理速度太快,而I/O操作太慢,而CPU资源比较稀缺,我们就想办法充分利用CPU及其他计算机组件。
二、进程和线程的区别?
两个概念的关注点都不同;进程是资源分配和保护的基本单位,就是CPU要分配资源是以进程为分配单位的,比如,分配物理内存会被映射到进程资源中;且进程会保护资源,比如进程中的一个线程崩溃了,不能影响其他进程的正常使用,之所以能做到这样,就是进程的资源都是独立的,跟其他进程资源分开的。而线程是进程中任务的执行路径,一个进程可以有若干个线程,线程共享进程里的资源,每个线程也有一个程序计数器和一些堆栈。
三、进程与进程之间的关系?
- 不知道彼此的存在,此时很存在竞争关系;
- 间接知道对方的存在,可能通过共享变量等;
- 知道对方的存在,一般协作关系,共同完成某件事情;
四、当多个进程并发执行的时候可以通过信号量进行交互,SEMWait和SEMSignal,其实这就是我们所说的P,V操作,分别相当于我们Java中所讲的加锁,解锁的操作;最经典的生产者和消费者问题,生产者有若干个,消费者只有一个,缓冲区大小是n。如果缓冲区没有东西存在,消费者不能消费,对于缓冲区而言,每次都只能有一个生产者或者消费者存在;
1 semphore mutex; //用于互斥; 2 semphore empty = n;//缓冲区有n个空格; 3 semphore full = 0; //刚开始没有物品,消费者不能消费; 4 5 void writer(){ 6 7 while(true){ 8 9 P(empty);//先判断缓冲区是否有空余;如果有的话看能否进入缓冲区 10 P(mutex); 11 //这个和上行位置不能错,否则会死锁,如果先加锁P(mutex)且缓冲区满,没有空闲,而消费者又不能进入缓冲区进行消费,就会死锁, 12 13 14 product(); 15 16 V(mutex); 17 V(full); //生产完东西后, 唤醒消费者; 18 19 } 20
void consumer(){
P(full);
P(mutex);
consume();
V(mutex);
V(empty);//已经消费过了,生产者可以再生产东西了
}
21 22 23 }
五、多个进程并发执行会带来一些问题,比如死锁和饥饿,特别是死锁,我们要想尽办法避免产生死锁;
死锁:一组进程由于互相竞争共享资源进入永久阻塞状态;很大情况下死锁是由于我们程序逻辑不合理引起的;
而产生死锁的充要条件有:
- 互斥:每个资源只能被一个进程占有且使用;
- 占有并等待:进程继续占有资源,并等待其他进程释放资源;
- 非抢占:资源被某个进程占有后,除非该进程主动释放资源,其他进程不得抢占该资源;
- 循环等待:进程组的每个进程都有其他进程请求的资源,且其他进程也有该进程请求的资源;
我们怎么处理死锁,主要有三种方法:
预防:进程要死锁必须要满足上述四个条件,想办法让其中一个方法不能实现,其中方法一改动不了,改动2,3,4;
避免:需要提前知道进程申请资源的最大数目,主要有两种方法实现:1.如果新申请的进程会导致死锁,那该进程就不申请了;2、如果进程申请新的资源会导致死锁,那么就不申请该资源了。
5.1、拒绝申请新进程
R= {R1,R2...Rj} 每种资源的总数量;
V = {V1,V2...Vj} 每种资源剩余的数量;
C = C11,C12...C1j
C21......
Ck1....
Cn1,Cn2...Cnj C矩阵表示进程i需要资源j的数量
A = A11,A12...A1j
A21...
Ak1...
An1,An2...Anj A矩阵表示进程i已经分配的资源;
其中要满足一些条件;1、Rj= Vj +ΣCij(i=1...n),对于所有的j;2、Aij <= Cij <= Rj;
2.拒绝资源分配(银行家算法)
状态:就是资源分配各个进程后,四个矩阵的取值情况;
安全状态:至少有一个进程可以正常执行完;执行完以后释放该进程占据的资源;