进程间通信之面包师问题
来源:互联网 发布:vscode 文件路径提示 编辑:程序博客网 时间:2024/04/30 09:24
作者:潘家邦
2012年12月6日
面包师问题是进程间通信的经典问题。本文就面包师问题进行讨论,并在linux上编程实现。平台说明:Linux Mint 14,G++ 4.7.2。
问题描述
面包师有很多面包和蛋糕,由n个销售人员销售。每个顾客进店后先取一个号,并且等着叫号。当一个销售人员空闲下来,就叫下一个号。请分别编写销售人员和顾客进程的程序。
问题分析
使用信号量解决该问题。首先分析客户和销售人员之间的关系。从问题描述中我们可以看出,客户是排队等待的,而且只有一条队列。当新出现一个客户,则等待队列的长度加一。当销售人员叫号,则等待队列长度减一。客户排队从另一种角度来看,可以认为客户进程被阻塞了,在PV操作中,V操作是不会导致阻塞的,所以把队列长度当作信号量是不会导致客户进程被阻塞的。注意到一共有n个销售人员,当一个销售人员空闲下来,就叫下一个号。换个角度看,销售人员最大空闲人数为n,每出现一个客户,则空闲人数减一,当空闲人数为0时,新出现的客户被阻塞,直到空闲人数大于0,阻塞的客户才被唤醒。我们还发现,不止客户在排队,销售人员在排队的情况也会发生。假设客户的等待队列长度为0,即没有客户在排队,那么这时销售人员应该被阻塞,直到新来一个客户,将销售人员唤醒。于是队列长度成为第二个信号量。
问题求解
算法描述
模仿《现代操作系统(第二版)》的格式,下面分别给出销售人员和客户的伪代码。
typedef int Semaphore;Semaphore num_of_free = 0;Semaphore num_of_waiting = 0;void customer(){ get_code(); up(&num_of_waiting); down(&num_of_free); buy_cake(); up(&num_of_free);}void salesman(){ up(&num_of_free); while(true) { down(&num_of_waiting); sell_cake(); }}
接下来将解释这段伪代码的逻辑。每启动一个salesman, 则空闲的salesman数目增加。在某一时刻,没有customer在等待,num_of_waiting为0,则salesman在执行到循环体的down语句将被阻塞。如果来了一个customer,则customer的第一个up语句将有可能唤醒某个处于阻塞态的salesman,然后执行down语句。如果没有salesman处于“空闲”,即num_of_free为0,则customer在down语句内被阻塞,直到某个salesman被启动或者某个customer完成了buy_cake并发起up操作来唤醒其他被阻塞在num_of_free上的customer。于是这就保证了num_of_free这个信号量不会大于n。
具体实现
使用Linux的System V风格信号量,主要可执行文件为cumtomer、salesman,分别是客户和销售人员的模拟程序。另外还有可执行文件state,用于输出当前信号量的值;可执行文件state_clear,用于将信号量置零。Python脚本coming.py,用于模拟客户到来的情况。所有可执行文件需要在root权限下执行。文件列表:coming.py makefile semaphore.cpp state_clear.cpp customer.cpp salesman.cpp semaphore.h state.cpp
semaphore.h
我对linux的信号量的操作做了一些封装,隐藏其复杂性,使之在本问题的主要代码中看起来简洁。这是封装之后的接口。
#ifndef SEMAPHORE_H#define SEMAPHORE_H#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>union semun{ int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf;};int semaphore_create();int output_semaphore(int sid);int up_num_of_waiting(int sid);int down_num_of_waiting(int sid);int up_num_of_free(int sid);int down_num_of_free(int sid);#endif
semaphore.cpp
这是semaphore接口的实现。
#include "semaphore.h"#include <stdio.h>int semaphore_create(){ int key = ftok(".", 1); return semget(key, 2, IPC_CREAT);}int output_semaphore(int sid){ printf("num of waiting: %d\n", semctl(sid, 0, GETVAL)); printf("num of free : %d\n", semctl(sid, 1, GETVAL));}int up_num_of_waiting(int sid){ sembuf operation = {0, 1, SEM_UNDO}; return semop(sid, &operation, 1);}int down_num_of_waiting(int sid){ sembuf operation = {0, -1, SEM_UNDO}; return semop(sid, &operation, 1);}int up_num_of_free(int sid){ sembuf operation = {1, 1, SEM_UNDO}; return semop(sid, &operation, 1);}int down_num_of_free(int sid){ sembuf operation = {1, -1, SEM_UNDO}; return semop(sid, &operation, 1);}
customer.cpp
这是客户程序的实现。
#include <unistd.h>#include <iostream>#include "semaphore.h"using namespace std;int main(){ int pid = getpid(); cout << "a customer come, get pid " << pid << endl; int sid = semaphore_create(); up_num_of_waiting(sid); down_num_of_free(sid); cout << "a salesman is free, pid "<< pid << " go for her" << endl; up_num_of_free(sid); return 0;}
salesman.cpp
这是销售人员的的实现。
#include <iostream>#include "semaphore.h"using namespace std;int main(){ int sid = semaphore_create(); up_num_of_free(sid); while(true) { down_num_of_waiting(sid); cout << "a customer is waiting, I call him" << endl; } return 0;}
state.cpp
可以方便的查看信号量的值。
#include "semaphore.h"int main(){ int sid = semaphore_create(); output_semaphore(sid); return 0;}
state_clear.cpp
将所有信号量置零。方便重复调试。
#include "semaphore.h"int main(){ int sid = semaphore_create(); semun sem; sem.val = 0; semctl(sid, 0, SETVAL, sem); semctl(sid, 1, SETVAL, sem); return 0;}
makefile
自动化编译脚本。
baker_problem: customer salesman state state_clear.PHONY : baker_problemcustomer: customer.o semaphore.o g++ -o customer customer.o semaphore.osalesman: salesman.o semaphore.o g++ -o salesman salesman.o semaphore.ostate:state.o semaphore.o g++ -o state state.o semaphore.ostate_clear: state_clear.o semaphore.o g++ -o state_clear state_clear.o semaphore.osemaphore.o:customer.o:salesman.o:state.o:state_clear.o:clean: rm *.o customer salesman state state_clear
coming.py
使用python按照一定的时间间隔启动cuntomer。
#!/usr/bin/pythonimport oswhile True: os.system('sudo ./customer') os.system('sleep 5')
<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
- 进程间通信之面包师问题
- 面试题之进程间通信问题
- [进程通信] 进程间通信 之 管道
- ios进程间通信问题之二----XPC
- ios进程间通信问题之二----XPC Service
- 进程间通信之管道通信
- Linux进程间通信之管道通信
- Linux进程间通信之管道通信
- android 进程间通信之SOCKET通信
- 进程间通信之消息通信
- 通信之进程间通信-AIDL
- 进程间的通信之信号通信
- 进程间通信之消息队列通信
- 进程间通信之匿名管道通信
- 进程间通信之信号量通信
- 进程间通信之管道通信
- 进程间通信之初探
- 进程间通信之信号
- FusionCharts控件保存图片后没有触发FC_Exported事件的解决
- FAQ: How do I debug a custom rule?
- 书斋
- 7 Steps to Write Your Own Custom Rule using FXCOP
- IIs 映射 问题
- 进程间通信之面包师问题
- 数据结构与算法之:块状链表(或者叫块状数组)
- 电商战略哪来“大师”们说的那么复杂?
- qwt安装使用教程
- C#计算发表时间为几个月,几天前,几小时前,几分钟前,或几秒前
- 腾讯之 张小龙
- PHP生成xml文件方法
- linux 与windows的内存分配
- Javascript 函数初探