⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 philosopher.c

📁 OS的经典问题:哲学家吃饭问题!用gcc编译
💻 C
字号:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <signal.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>

#define PhNum		5
#define LEFT		(PhNum+argi-1)%PhNum
#define RIGHT		(argi+1)%PhNum

#define THINKING	0
#define HUNGRY		1
#define EATING		2

#define THINKTIME	4
#define EATTIME		3

//#define SHMKEY (key_t) 0x100 
//#define SEMKEY (key_t) 0x200 

//#define IFLAGS (0600|IPC_CREAT|IPC_EXCL) 

union semun 
{
	int val;
	struct semid_ds *buf;
	ushort *array;
};

void p_operate(int semid,ushort semnum) 
{
	struct sembuf thesops;
    thesops.sem_num=semnum;
  	thesops.sem_op=-1; 
	thesops.sem_flg=SEM_UNDO;
    //thesops.sem_flg=0; 
    semop(semid,&thesops,1); 
}
void v_operate(int semid,ushort semnum) 
{
	struct sembuf thesops;
    thesops.sem_num=semnum;
  	thesops.sem_op=1; 
	thesops.sem_flg=SEM_UNDO;
    //	thesops.sem_flg=0; 
    semop(semid,&thesops,1); 
}

void think(int argi)
{
	printf("I'm philosopher #%d,I will think for %d seconds\n",argi,argi+THINKTIME);
	sleep(argi+THINKTIME);
}

void eat(int argi)
{
	printf("I'm philosopher #%d,I will eat for %d seconds\n",argi,argi+EATTIME);
	sleep(argi+EATTIME);
}

void test(int argi,char *state,int semid)
{
	if(state[argi]==HUNGRY&&state[LEFT]!=EATING&&state[RIGHT]!=EATING)
	{
		state[argi]=EATING;
		printf("Hehe,philosopher #%d can eat now\t",argi);
		printf("// #%d 可以吃饭\n",argi);
		v_operate(semid,argi);
	}
	else 
		if (state[argi]!=HUNGRY)
			printf("Faint,philosopher #%d don't want to eat\t // #%d 还不饿",argi);
		else printf("Oh,philosopher #%d can't eat now!\t //#%d 还不能吃饭",argi);
}

void take_forks(int argi,char *state,int semid)
{
	p_operate(semid,PhNum);
	state[argi]=HUNGRY;
	printf("Philosopher #%d is hungry.Can he eat...\n",argi);
	test(argi,state,semid);//测试能否吃饭
	v_operate(semid,PhNum);
	p_operate(semid,argi);
}
void put_forks(int argi,char *state,int semid)
{
	p_operate(semid,PhNum);
	state[argi]=THINKING;
	printf("Philosopher #%d eat O.K..Can his neighbours eat...\t",argi);
	printf("// #%d 吃饭完毕\n",argi);
	test(LEFT,state,semid);
	test(RIGHT,state,semid);
	v_operate(semid,PhNum);
}
void philosopher(int argi,char *state,int semid)
{
	while(1)
	{
		think(argi);
		take_forks(argi,state,semid);
		eat(argi);
		put_forks(argi,state,semid);
	}
}

/*主控过程的实现*/
int main(int argc,char *argv[])
{
    int semkey,shmkey,semid,shmid,fori,forki,mynum;
    char *state; 
	union semun arg1; 
	struct shmid_ds arg2;
	ushort array[PhNum+1];

	if((semid=semget(IPC_PRIVATE,PhNum+1,0600|IPC_CREAT))==-1)
        {
			perror("Semget error!");
			exit(1);
		}
   	if((shmid=shmget(IPC_PRIVATE,PhNum,0600|IPC_CREAT))==-1)
        {
          semctl(semid,0,IPC_RMID,arg1);
          perror("Shmget error!");
          exit(1);
        }

    array[PhNum]=1;
    for(fori=0;fori<PhNum;fori++) array[fori]=0;	/*设置信号量数组初值*/
    arg1.array=array;
	if ((semctl(semid,PhNum+1,SETALL,arg1))==-1)   /*设置各信号量的初始值*/
	{  
        semctl(semid,0,IPC_RMID,arg1);
        shmctl(shmid,IPC_RMID,&arg2);
        perror("Set default error!");
        exit(1);
       }

    if ((state=shmat(shmid,0,0))==(char *)-1){ /*将共享内存映射到当前进程地址空间*/
        semctl(semid,0,IPC_RMID,arg1);
        shmctl(shmid,IPC_RMID,&arg2);
        perror("Shmat error!");
        exit(1);
        }

    for (fori=0;fori<PhNum;fori++) 
		state[fori]=THINKING;  /*初始化状态数组*/
    signal(SIGINT,SIG_IGN);    /*将进程对中断信号的处理设为忽略*/
    
	for (fori=1;fori<=PhNum;fori++)
	{  /*创建5个哲学家子进程*/
		while((forki=fork())==-1);
		if (!forki){    /*子进程执行代码*/
			mynum=fori-1;
			signal(SIGINT,SIG_DFL);   /*设置子进程对SIGINT信号的处理过程*/
			break;
				}
	}
	if(forki){
		while(wait((char *)0)!=-1);   /*等待子进程执行结束,此处的(char *)0相当于NULL,即忽略返回状态*/
		semctl(semid,0,IPC_RMID,arg1);
		shmdt(state);
		shmctl(shmid,IPC_RMID,&arg2);
		printf("\nI'm monitor.All is over...\n");
	}
	else philosopher(mynum,state,semid);  /*子进程调用*/
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -