信号量的使用
根据信号量的含义: (1)信号量是一个需要被多个进程共享的整数; (2)根据信号量的值让相应的进程睡眠(sleep_on)或唤醒(wake_up),睡眠或唤醒的操作对象是进程PCB (3)在操作这个整数时要进行临界区保护,可以调用Lamport面包店算法、开关终端操作等,不管从哪一个方面来说,应该将信号量的实现放在操作系统内核,并将信号的P,V操作实现成系统调用,因为将一个变量放在操作系统内核以后所有的进程就可以共享了,另外在操作系统内核中操作PCB、开关终端等动作既简单可行、安全可靠,又能向用户屏蔽细节。 通常,信号量实现为操作系统内核中的一个数据对象,而P,V操作实现为操作系统给上层用户程序的两个系统调用。 POSIX标准针对信号量定义了如下四种基本系统调用
sem_t *sem_open(const char *name, int oflag, mode_t mode,unsigned int value)
int sem_unlink(const char *name)
int sem_wait(sem_t *sem)
int sem_post(sem_t *sem)
编写一个应用程序“pc.c”来模拟经典的生产者—消费者问题: (1)建立一个生产者进程,5个消费者进程; (2)通过操作同一个文件来建立一个共享缓存区; (3)生产者依次向缓存区写入整数0,1,2,…,499 (4)每个消费者进程从缓存区中读取100个数,没读取一个数就打印到标准输出上; (5)缓存区最多只能保存10个数,即缓存区文件中最多存放10个数
main()
{
if(!fork()){
empty = sem_open("empty", 10)
full = sem_open("full", 0)
mutex = sem_open("mutex",1)
for (i = 0; i<500; i++){
sem_wait(empty);
sem_wait(mutex);
sem_post(mutex)
sem_post(full)
}
}
if(!fork()){
empty = sem_open("empty", 10)
}
}
有正有负信号量的实现
int sys_sem_wait(sem_t *sem){
cli();
sem->value--;
if(sem[i]->value < 0){
current_state = SLEEP;
schedule();
}
sti();
return 0;
}
int sys_sem_post(sem_t *sem){
cli();
sem->value++;
if(sem[i]->value < 0){
p_state = SLEEP;
schedule();
}
sti();
return 0;
}
死锁现象的出现
如果在缓存区已满的情况下,生产者进程想要继续往缓存区放入item,生产者会首先进行p(mutex)并成功地获得了互斥信息量mutex ;接下来生产者在要获得empty信号(即执行P(empty))时发现缓存区已满,从而停下来等待,当消费者进程执行P(mutex)时发现这个互斥信号量仍然被生产者进程占有而没有释放,当然消费者进程只能等待,等待生产正执行Item放入缓存区释放mutex。
死锁出现地条件
死锁发生地四个基本条件: (1)互斥:资源不能被共享,一个资源只能被一个进程使用。 (2)不可剥夺:进程已获得地资源,在未使用完之前,不能强行剥夺。 (3)请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不妨。 (4)循环等待:若干进程之间形成一种首尾详解的循环性资源等待关系
银行家
和银行贷款问题进行类比: (1)银行时操作系统,资金就是资源,客户相当于要申请资源的进程 (2)客户能最终偿还带宽需要银行满足客户的全部贷款请求,相当于操作系统满足进程的所有资源请求,即让进程执行完成,不造成死锁; (3)银行判断贷款请求是否应该被批准相当于对操作系统盘对进程资源是否可以被允许,英航没有损失相当于没有死锁; (4)操作系统判断这个资源请求是否安全的算法就是银行家判断此次贷款是否安全的算法
int available[1..m]
int Allocation[1..n,1..m]
int Max[1..n,1..m]
int work[1..m]
bool Finish[1..n]
work = available
Finish[1..n]=false
while(true)
{
find = false;
for(i=1; i<=n;i++)
{
if(Finish[i] == false && work +Allocation[i] >= Max[i])
{
Finish[i] = true;
Work = work + Allocation[i]
find = true;
}
}
if (find == false){goto END;}
}
|