生産者和消費者
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/shm.h>
#include<sys/mman.h>
#include<stdio.h>
#include<stdlib.h>
#define SHM_SIZE (1024*1024)
#define SHM_MODE 0600
#define SEM_MODE 0600
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
#endif
struct ShM{
int start;
int end;
}* pSM;
int count=30;//計數器,produce執行30次後終止程式
const int num_of_consumer = 3;//消費者數量
const int size_of_buffer=5;//緩沖區大小
int shmId = -1;
int semSetId = -1;
union semun su;//sem union,用于初始化信号量
void semWait(int semSetId,int semNum)
{
struct sembuf sb;
sb.sem_num = semNum;
sb.sem_op = -1;//表示信号量減1
sb.sem_flg = SEM_UNDO;//程序結束時,相應的操作被取消
//第 3 個參數表示數組sb的大小
if(semop(semSetId,&sb,1)<0)
{
perror("semWait failed!");
exit(1);
}
}
void semSignal(int semSetId,int semNum)
{
struct sembuf sb;
sb.sem_num = semNum;
sb.sem_op = 1;//表示信号量加1
sb.sem_flg = SEM_UNDO;
//第 3 個參數表示數組sb的大小
if(semop(semSetId,&sb,1)<0)
{
perror("semSignal failed!");
exit(1);
}
}
void init()
{
//緩沖區配置設定以及初始化
if((shmId = shmget(IPC_PRIVATE,SHM_SIZE,SHM_MODE))<0)
{
perror("create shared memory failed!");
exit(1);
}
pSM = (struct ShM*) shmat(shmId,0,0);
pSM->start = 0;
pSM->end = 0;
if((semSetId = semget(IPC_PRIVATE,3,SEM_MODE))<0)
{
perror("create semaphore failed!");
exit(1);
}
//空閑塊數量 e
//信号量初始化,其中 su 表示 union semun
su.val = size_of_buffer;//目前庫房還可以接收多少産品
if(semctl(semSetId,0,SETVAL, su) < 0){
perror("semctl failed");
exit(1);
}
//可用數量 n
su.val = 0;//目前沒有産品
if(semctl(semSetId,1,SETVAL,su) < 0){
perror("semctl failed");
exit(1);
}
//權限 s
su.val = 1;//為1時可以進入緩沖區
if(semctl(semSetId,2,SETVAL,su) < 0){
perror("semctl failed");
exit(1);
}
}
void produce()
{
int last = pSM->end;
pSM->end = (pSM->end + 1) % size_of_buffer;
printf("PID=%d 生産 %d\n",getpid(),last);
}
void consume()
{
int last = pSM->start;
pSM->start = (pSM->start - 1) % size_of_buffer;
printf("PID=%d 消耗 %d\n",getpid(),last);
}
/*
生産者
*/
void producer()
{
while(1)
{
semWait(semSetId,0);
semWait(semSetId,2);
produce();
semSignal(semSetId,2);
sleep(1);
semSignal(semSetId,1);
count -= 1;
if(count==0)
{
printf("end all!\n");
exit(1);
}
}
}
/*
消費者
*/
void consumer()
{
while(1)
{
semWait(semSetId,1);//有産品才能消費
semWait(semSetId,2);//鎖定緩沖區
consume();
semSignal(semSetId,2);//釋放緩沖區
semSignal(semSetId,0);//增加空間
sleep(2);
}
}
int main()
{
int child = -1;
init();
for(int i=1;i<=num_of_consumer;i+=1)
{
if((child = fork())<0)
{
perror("the fork failed!");
exit(1);
}
else if(child==0)
{
printf("我是第 %d 個消費者子程序,PID=%d\n",i,getpid());
consumer();
break;
}
}
if(child>0)
{
producer();
}
return 0;
}
讀者和寫者
#include<unistd.h>
#include<sys/types.h>
#include<sys/sem.h>
#include<sys/mman.h>
#include<sys/ipc.h>
#include<stdio.h>
int *critical;
int createSem()//建立信号量
{
return semget((key_t)1000,2,IPC_CREAT|0600);
} //第二個參數是我們要建立的信号量個數
void initSignal(int semid,int index,int value)//初始化信号量
{
semctl(semid,index,SETVAL,value);
}
void make_critical()//建立緩沖區
{
critical = mmap(NULL,10*sizeof(int),PROT_READ|
PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
critical[0]=-1;//臨界區初始化為-1;
critical[1]=0;//讀者數量初始化為0;
}
void semWait(int semid,int index)//判斷目前程序是否進去緩沖區,,被占用就挂起
{
struct sembuf sem_buf;
sem_buf.sem_num=index;
sem_buf.sem_op=-1;
sem_buf.sem_flg=SEM_UNDO;
semop(semid,&sem_buf,1);
}
void semSignal(int semid,int index)//喚醒一個在阻塞隊列中等待的程序
{
struct sembuf sem_buf;
sem_buf.sem_num=index;
sem_buf.sem_op=1;
sem_buf.sem_flg=SEM_UNDO;
semop(semid,&sem_buf,1);
}
void reader(int semid)
{
while(1)
{
semWait(semid,1);
critical[1]++;
if (critical[1]==1)
semWait(semid,0);
semSignal(semid,1);
printf("讀者讀到的資料是: %d\n",critical[0]);
semWait(semid,1);
critical[1]--;
if (critical[1]==0)
semSignal(semid,0);
semSignal(semid,1);
}
}
void writer(int semid)
{
while(1)
{
semWait(semid,0);
printf("寫者寫入的資料:");
scanf("%d",&critical[0]);
printf("寫者更新後的資料: %d\n",critical[0]);
semSignal(semid,0);
}
}
int main()
{
int semid=createSem();
initSignal(semid,0,1);//初始化控制寫者信号量W
initSignal(semid,1,1);//初始化控制讀者信号量R
//the critical number is init as -1 the writer will update it
make_critical();//create critical region
pid_t child=fork();
if(child==0)
{
reader(semid);
}
else
{
writer(semid);
}
return 0;
}
說明:這份代碼有借鑒網絡上的代碼,但是出處已經不記得了。如侵權請留言删除。