本文主要分析的是多生產者,多消費者以及多個資源的進程間的同步和互斥機制。
作業系統中我們已經學習過了生產者和消費者之間的同步互斥模型
生產者:
{
生產一個產品;
p(empty);
p(mutex);
產品入buffer;
v(mutex);
v(full);
}
消費者
{
p(full);
p(mutex);
從buffer中取出產品;
v(mutex);
v(empty);
}
在真正編程實現是,採用IPC機制,因此要為生產者和消費者共同使用的變數建立共用記憶體地區並且將該共用記憶體區域對應到進程的地址空間中,從而可以直接對該地址空間
進行操作。
而且,在該模型中,使用了三個訊號量,因此要採用linux中的訊號量集機制。
#include <shm.h>int main(){int num;int shmid_goods,shmid_index,semid;char* shmaddr=NULL;int *indexaddr=NULL;int is_noexist=0;num=10;//建立貨物的共用記憶體地區,並且連結到進程使用者空間。大小為10位元組。if((shmid_goods=createshm(".",'s',num))==-1){if(errno==EEXIST){if((shmid_goods=openshm(".",'s'))==-1){exit(1);}}else{perror("create shared memory failed\n"); exit(1);}}//返回共用記憶體地區的標識符if((shmaddr=shmat(shmid_goods,(char*)0,0))==(char*)-1){perror("attach shared memory error\n");exit(1);}/*建立一個共用記憶體,用於存放生產者和消費者在buffer中的索引號。 該索引指向了生產/消費的buffer的索引值。*/if((shmid_index=createshm(".",'z',2))==-1){if(errno==EEXIST){if((shmid_index=openshm(".",'z'))==-1){exit(1);}}else{perror("create shared memory failed\n"); exit(1);}}else{is_noexist=1;}//attach the shared memory to the current processif((indexaddr=shmat(shmid_index,(int*)0,0))==(int*)-1){perror("attach shared memory error\n");exit(1);}/* 索引初始化為0*/if(is_noexist){indexaddr[0]=0;indexaddr[1]=0;}/*該函數用於產生訊號量集,並通過訊號量集標識符設定訊號量的值mutex:1empty:10full:0前兩個參數用於產生key。*/if((semid=createsem(".",'t',3,0))==-1){if(errno==EEXIST){if((semid=opensem(".",'t'))==-1){exit(1);}}else{perror("semget error:");exit(1);}}else{union semun arg; //seting value for mutex semaphore arg.val=1; if(semctl(semid,0,SETVAL,arg)==-1) {perror("setting semaphore value failed\n"); return -1; } //set value for synchronous semaphore arg.val=num; //the num means that the producer can continue to produce num products if(semctl(semid,1,SETVAL,arg)==-1) {perror("setting semaphore value failed\n"); return -1; } //the last semaphore's value is default //the default value '0' means that the consumer is not use any product now }int goods=0;while(1){p(semid,1);sleep(3);p(semid,0);//producer is producing a productgoods=rand()%10;///將貨物buffer中編號為indexaddr[0]的buffer中放入貨物shmaddr[indexaddr[0]]=goods;printf("producer:%d produces a product[%d]:%d\n",getpid(),indexaddr[0],goods);///同時索引值+1。indexaddr[0]=(indexaddr[0]+1)%10;v(semid,0);sleep(3);v(semid,2);}}
#include <shm.h>int main(){int num;int shmid_goods,shmid_index,semid;char* shmaddr=NULL;int *indexaddr=NULL;int is_noexist=0;num=10;//建立貨物的共用記憶體地區,並且連結到進程使用者空間。大小為10位元組。if((shmid_goods=createshm(".",'s',num))==-1){if(errno==EEXIST){if((shmid_goods=openshm(".",'s'))==-1){exit(1);}}else{perror("create shared memory failed\n"); exit(1);}}//返回共用記憶體地區的標識符if((shmaddr=shmat(shmid_goods,(char*)0,0))==(char*)-1){perror("attach shared memory error\n");exit(1);}/*建立一個共用記憶體,用於存放生產者和消費者在buffer中的索引號。 該索引指向了生產/消費的buffer的索引值。*/if((shmid_index=createshm(".",'z',2))==-1){if(errno==EEXIST){if((shmid_index=openshm(".",'z'))==-1){exit(1);}}else{perror("create shared memory failed\n"); exit(1);}}else{is_noexist=1;}//attach the shared memory to the current processif((indexaddr=shmat(shmid_index,(int*)0,0))==(int*)-1){perror("attach shared memory error\n");exit(1);}/* 索引初始化為0*/if(is_noexist){indexaddr[0]=0;indexaddr[1]=0;}/*該函數用於產生訊號量集,並通過訊號量集標識符設定訊號量的值mutex:1empty:10full:0前兩個參數用於產生key。*/if((semid=createsem(".",'t',3,0))==-1){if(errno==EEXIST){if((semid=opensem(".",'t'))==-1){exit(1);}}else{perror("semget error:");exit(1);}}else{union semun arg; //seting value for mutex semaphore arg.val=1; if(semctl(semid,0,SETVAL,arg)==-1) {perror("setting semaphore value failed\n"); return -1; } //set value for synchronous semaphore arg.val=num; //the num means that the producer can continue to produce num products if(semctl(semid,1,SETVAL,arg)==-1) {perror("setting semaphore value failed\n"); return -1; } //the last semaphore's value is default //the default value '0' means that the consumer is not use any product now }int goods=0;while(1){p(semid,1);sleep(3);p(semid,0);//producer is producing a productgoods=rand()%10;///將貨物buffer中編號為indexaddr[0]的buffer中放入貨物shmaddr[indexaddr[0]]=goods;printf("producer:%d produces a product[%d]:%d\n",getpid(),indexaddr[0],goods);///同時索引值+1。indexaddr[0]=(indexaddr[0]+1)%10;v(semid,0);sleep(3);v(semid,2);}}
#include <shm.h>int main(int argc,char **argv){int num;int shmid_goods,shmid_index,semid;char* shmaddr=NULL;int* indexaddr=NULL;int is_noexist=0;num=10;//create a shared memory as goods buffer//注意,生產消費者的相同的共用地區用了同樣的參數,//所以會禪城同樣的key值。if((shmid_goods=createshm(".",'s',num))==-1){if(errno==EEXIST){if((shmid_goods=openshm(".",'s'))==-1){exit(1);}}else{perror("create shared memory failed\n"); exit(1);}}//attach the shared memory to the current processif((shmaddr=shmat(shmid_goods,(char*)0,0))==(char*)-1){perror("attach shared memory error\n");exit(1);}//create a shared memory as indexif((shmid_index=createshm(".",'z',2))==-1){if(errno==EEXIST){if((shmid_index=openshm(".",'z'))==-1){exit(1);}}else{perror("create shared memory failed\n"); exit(1);}}else{is_noexist=1;}//attach the shared memory to the current processif((indexaddr=shmat(shmid_index,(int*)0,0))==(int*)-1){perror("attach shared memory error\n");exit(1);}if(is_noexist){indexaddr[0]=0;indexaddr[1]=0;}//create a semaphore set including 3 semaphoresif((semid=createsem(".",'t',3,0))==-1){if(errno==EEXIST){if((semid=opensem(".",'t'))==-1){exit(1);}}else{perror("semget error:");exit(1);}}else{union semun arg; //seting value for mutex semaphore arg.val=1; if(semctl(semid,0,SETVAL,arg)==-1) {perror("setting semaphore value failed\n"); return -1; } //set value for synchronous semaphore arg.val=num; //the num means that the producer can continue to produce num products if(semctl(semid,1,SETVAL,arg)==-1) {perror("setting semaphore value failed\n"); return -1; } //the last semaphore's value is default //the default value '0' means that the consumer is not use any product now }int goods=0;while(1){p(semid,2);sleep(1);p(semid,0);///取出一個貨物。goods=shmaddr[indexaddr[1]];printf("consumer:%d consumes a product[%d]:%d\n",getpid(),indexaddr[1],goods);//索引值加一indexaddr[1]=(indexaddr[1]+1)%num;v(semid,0);sleep(1);v(semid,1);}}