码迷,mamicode.com
首页 > 系统相关 > 详细

进程同步和信号量

时间:2016-05-01 23:09:10      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:

进程的同步

进城合作:多进程完成同一个任务

?

实例1:

司机 ? ? ? ? ? ? ? ? ? ? ? ? ?售票员

while)true){ ? ? ? ? ? ? ? ? ?while)true){

等待 启动车辆; ? ? ? ? ? ? ? ? ? ?关门; 发送信号

? ? 正常运行; ? ? ? ? ? ? ? ? ? ?售票;

? ? 到站停车;发送信号 ? ? ? ? ? ?等待 开门;

} ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

两个进程如何实现同步合作? 通过信号

实例2:文档打印

问题:如果进程之间完全不知道对方的存在,会产生怎样的错误?联系实际

?

技术分享

?

实际上的例子:生产者-消费者实例

共享数据

? 这些都是用户态

技术分享

?

生产者进程

while(true){

? ?while(counter == BUFFER_SIZE)

? ? ? ? ; //阻塞 ?缓冲区满,生产者停

? ?buffer[in] = item;

? ?in = (in+1)%BUFFER_SIZE;

? ?counter++; //发信号让消费者走

}

?

消费者进程

while(true){

? while(counter == 0)

? ? ; //阻塞 ?缓冲区空,消费者停

? item=buffer[out];

? out = (out-1)%BUFFER_SIZE;

? counter--; //发信号让生产者走

}

?

等待是进程同步的核心

?

什么是进程同步?什么地方停,什么地方走?

进程同步?事实上就是让进城走走停停,来保证多进程合作的合理有序

?

只发信号还不能解决全部问题

技术分享

1.缓冲区满以后生产者P1生产一个item放入,会sleep

2.有一个生产者P2生产一个item放入,会sleep

3.消费者C执行1次循环,counter == BUFFER_SIZE - 1, 发信号给P1, P1 wake up。

4.消费者C再执行1次循环,counter == BUFFER_SIZE - 2,P2不能被唤醒。

?

counter无法区分有多少生产者进程,不仅需要唤醒进程(发送信号),还需要一个量用来记录睡眠进程的数量,来决定是否要发信号。

?

这就引出了信号量

? ?

从信号到信号量

不只是等待信号,发信号? 对应睡眠和唤醒

还能记录一些信息

  • 能记录有2个进程等待就可以了 可以使用优先队列或者是栈来存储
  • 1.缓冲区满,P1执行,P1 sleep,记录下一个进程等待?sem = -1
  • 2.P2执行,P2sleep,记录下两个进程等待 ??sem = -2
  • 3.C执行1次循环,发现两个进程等待,wakeup一个 wakeup P1?sem=-1
  • C再执行1次循环,发现一个进程等待,wakeup一个 wakeup P2?sem=0
  • C再执行1次循环4,发现没有进程等待,sem = 1
  • P3执行

总结:

什么时候减一?

当有一个进程sleep,信号量-1

什么时候加一?

当发现信号量是负的,信号量+1,并且发信号wakeup; 如果发现信号量是正的,那么不发信号,累加信号量。

?

问题:一种资源的数量是8,这个资源对应的信号量的当前值是2,说明():

技术分享

资源的数量是8,说明初始的sem是8,当前的信号量变为2,说明没有进程在等待等待这个资源。

?

什么是信号量?信号量的定义

信号量:1965年,由荷兰学者Dijkstra提出的一种特殊变量,量用来记录,信号用来sleep和wakeup

?

struct semaphore

{

? ? int value; //记录资料个数

? ? PCB *queue; //记录等待在该信号量上的进程

}

P(semaphore s); //消费资源

V(semphore s); //产生资源

?

P(semphore s)

{

? ? s.value--;

? ? if(s.value < 0){

? ? ? ? sleep(s.queue);?

? ? }

}

?

问:V(s)的代码?

V(semphore s){

? ?s.value++;

? if(s.value <= 0){

? ? wakeup(s.queue);

? }

}

?

Producer(item){

? ? P(empty);

? ? P(mutex);

? ? 读入in;将item写入到in的位置上;

? ? V(mutex);

? ? V(full);

}

?

Constumer() {

? ? P(full);

? ? P(mutex);

? ? 读入out;从文件out位置读出到item;打印item;

? ? V(mutex);

? ? V(empty);

}

?

用信号量解决生产者-消费者问题

int fd = open("buffer.txt");

write(fd, 0, sizeof(int)); //写in

write(fd, 0, sizeof(int)); //写out

?

semaphore full = 0;

semaphore empty = BUFFER_SIZE;

semaphore mutex = 1;

?

如何理解用信号量的生产者消费者代码?

full用来判断是否为空,empty用来判断是否为满。通过P和V来睡眠和唤醒进程,并释放信号量。

?

如何实现互斥访问?

当进入缓冲区时,将mutex的值变为0,用完之后在释放。

?

?

进程同步和信号量

标签:

原文地址:http://www.cnblogs.com/ACFLOOD/p/5451409.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!