linux进程协作-一个小例子
爸爸给女儿和儿子喂水果。爸爸随机挑选橘子或者苹果,将橘子剥皮或者将苹果削皮放在盘子中,剥皮的速度比较快,而削皮的时间比较慢。女儿只吃橘子,儿子只吃苹果(当然我们假设女儿和儿子永远也吃不饱)。盘子只能装下3个水果。儿子吃得比较快,女儿吃得比较慢。
编程模拟该过程:
简单分析
信号量:
int accessplate = 1; //表示访问盘子的信号量
int apple = 0; //苹果个数
int orange = 0; //橘子
int emptyplates = 3; //空盘子
|
Father: P(emptyplates); produce a fruit if( is apple ) then P(accessplate) put apple in V(apple) V(accessplate) else P(accessplate) put orange in V(orange) V(accessplate) |
Boy: P(apple) P(accessplate) get an apple eat an apple V(emptyplates) V(accessplate)
|
Girl: P(orange) P(accessplate) get an orange eat an orange V(emptyplates) V(accessplate)
|
代码:
|
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/*overall varible*/
int numOfEmptyPlate_sem_id = 0; //number of empty plates.
int numOfApple_sem_id = 0; //number of apple
int numOfOrange_sem_id = 0; //number of orange
int getAccesstoPlate = 0; //get plate
int *plate = NULL; //3 PLATES
struct sembuf P, V; // p,v opration
void printPlates(const char *arg)
{
int i = 0;
printf("%s\nFruits in plates:", arg);
for(i=0; i<3; i++)
{
printf("%d ", plate[i]);
}
printf("\n");
}
void father_do() // PUT FRUITS in
{// 1 == apple, 2 == range
int i = 0;
semop( numOfEmptyPlate_sem_id, &P, 1); // P(empty plates)
if( rand()%100+1 > 50) //get an orange
{
sleep(1); //get an orange,sleep 1 seconds
semop( getAccesstoPlate, &P, 1); //P(plate)
printf("Father get access to the plates.\n");
printPlates("father:");
for(i=0; i<3; i++)
{
if( 0 == plate[i]) //find an empty plate, and put the furit in
{
printf("%d ", plate[i]);
plate[i] = 2;
break;
}
}
semop( numOfOrange_sem_id, &V, 1); //V(oranges)
printf("Father put an orange in plate.\n");
semop( getAccesstoPlate, &V, 1); //V(plate)
printf("Father put the plates back.\n");
}
else // get an apple
{
sleep(2); //get an apple,sleep 2 seconds
semop( getAccesstoPlate, &P, 1); //P(plate)
printf("Father get access to the plates.\n");
printPlates("father:");
for(i=0; i<3; i++)
{
if( 0 == plate[i]) //find an empty plate, and put the furit in
{
printf("%d ", plate[i]);
plate[i] = 1;
break;
}
}
semop( numOfApple_sem_id, &V, 1); //V(apples)
printf("Father put an apple in plate.\n");
semop( getAccesstoPlate, &V, 1); //V(plate)
printf("Father put the plates back.\n");
}
}
void girl_do() //EAT ORAGERS
{
int i = 0;
semop( numOfOrange_sem_id, &P, 1); //P(oranges)
sleep(2); //girl eat slowly,sleep 2 seconds
semop( getAccesstoPlate, &P, 1); //P(plate)
printf("Gilr get access to the plates.\n");
printPlates("girl:");
for( i=0; i<3; i++)
{
if( 2 == plate[i] )
{
printf("%d ", plate[i]);
plate[i] = 0; // eat an orange
break;
}
}
semop( numOfEmptyPlate_sem_id, &V, 1); // V(empty plates)
printf("Girl eat an orange.\n");
semop( getAccesstoPlate, &V, 1); //V(plate)
printf("Girl put the plates back.\n");
}
void boy_do() // EAT APPLES
{
int i = 0;
semop( numOfApple_sem_id, &P, 1); //P(apple)
sleep(1); //boy eat fast,sleep 1 seconds
semop( getAccesstoPlate, &P, 1); //P(plate)
printf("Boy get access to the plates.\n");
printPlates("boy:");
for( i=0; i<3; i++)
{
if( 1 == plate[i] )
{
printf("%d ", plate[i]);
plate[i] = 0; // eat an apple
break;
}
}
semop( numOfEmptyPlate_sem_id, &V, 1); // V(empty plates)
printf("Boy eat an apple.\n");
semop( getAccesstoPlate, &V, 1); //V(plate)
printf("Boy put the plates back.\n");
}
int main()
{
/*Process ID*/
pid_t father_id;
pid_t girl_id;
pid_t boy_id;
char op =' ';
srand( time(0)); // set rand seed
plate=(int *)mmap(NULL, sizeof(int)*3, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS,-1,0); //GET SHARE MEMORY
plate[0] = 0;
plate[1] = 0;
plate[2] = 0; //all plates are empty.
numOfApple_sem_id = semget( IPC_PRIVATE, 1, IPC_CREAT|00666);
numOfEmptyPlate_sem_id = semget( IPC_PRIVATE, 1, IPC_CREAT|00666);
numOfOrange_sem_id = semget( IPC_PRIVATE, 1, IPC_CREAT|00666);
getAccesstoPlate = semget( IPC_PRIVATE, 1, IPC_CREAT|00666);
//Set signal measurement value(3 apples, 0 oranges)
if( -1 == semctl(numOfApple_sem_id, 0, SETVAL, 0) ||
-1 == semctl(numOfEmptyPlate_sem_id, 0, SETVAL, 3) ||
-1 == semctl(numOfOrange_sem_id, 0, SETVAL, 0) ||
-1 == semctl(getAccesstoPlate, 0, SETVAL, 1) )
{
perror("Semctl serval Error!\n");
}
//init P,V opration
V.sem_num = 0;
V.sem_op = 1;
V.sem_flg = SEM_UNDO;
P.sem_num = 0;
P.sem_op = -1;
P.sem_flg = SEM_UNDO;
father_id = fork();
if( father_id < 0 )//Error occures
{
fprintf(stderr, "Fork father Fail.\n");
}
else if( 0 == father_id ) //father do
{
while(1)
father_do();
}
else
{
girl_id = fork();
if( girl_id <0 )//Error occures
{
fprintf(stderr, "Fork gril Fail.\n");
}
else if( 0 == girl_id ) //girl do
{
while(1)
girl_do();
}
else
{
boy_id = fork();
if( boy_id < 0) //Error Occures
{
fprintf(stderr, "Fork boy Fail.\n");
}
else if ( 0 == boy_id) //boy do
{
while(1)
boy_do();
}
else //main process
{
do{
op= getchar();
}while( op!='q');
exit(0);
}
}
}
return 0;
}
|
运行截图:


浙公网安备 33010602011771号