logo资料库

linux哲学家就餐3种方法代码实现.doc

第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
资料共9页,剩余部分请下载后查看
Linux上,用C语言信号量实现进程对临界资源的互斥访问
IPC_CREAT—创建新的信号量集
IPC_EXCEL—如果信号量集已经存在,则返回错误。
2.信号量机制实现进程对临界资源的互斥访问,资源使用者在使用临界资源之前“等待”信号量,资源
一、实验目的 1、了解进程互斥、同步及其程序实现; 2、了解进程通信,以及利用进程互斥实现进程通信。 二、实验内容 Linux 上,用 C 语言信号量实现进程对临界资源的互斥访问 1、 信号量机制的基本操作: 资源使用者在使用临界资源之前“等待”信号量 资源使用者使用完临界资源后“通知”信号量 2、C 语言实现: 注意:以下函数原形在 sys/types.h、sys/ipc.h 和 sys/sem.h 包含文件中。 A)创建信号量集 int semget(key_t key,int nsems,int semfllg) 其中:key—创建信号量集关键字。 nsems—信号量集中信号量的数量。 semflg—指定选项及其权限位。 IPC_CREAT—创建新的信号量集 IPC_EXCEL—如果信号量集已经存在,则返回错误。 --和文件、目录一样权限。 返回一个信号量集 ID--semid B) 获得一个已经存在的信号量集 int semget(key_t key,0,0) key—含义同上。 C)等待、通知一个信号量集
int semop(int semid,struct sembuf *sops,unsigned nsops) semid—由函数 semget()产生的。 sops—描述信号量的操作:等待、通知等 struct sembuf{ short sem_num;/*semaphore number */ short sem_op; /*semaphore operation:-1 for waiting*/ short sem_flg; /* operation flag :0、IPC_NOWAIT */ } nsops—指定信号量集中操作的信号量个数。 D) 控制信号量集的操作 int semctl(int semid,int semnum,int cmd,union semun arg) semid—由 semget()创建的信号量集标识。 semnum—信号量数量。 cmd—对信号量 semid 所进行的操作:SETALL—所有参数。 arg—对信号量集操作的初始数据。
arg 的类型: union semun{ int val; /* 仅用于参数 SETVAL*/ struct semid_ds *buf; /*指向 IPC_STAT 和 IPC_SET 的 semid_ds 结构 ushort *array; /*用于 GETALL 和 SETALL:指向一个初值的数 */ */ }; union semun arg; 本参数主要用于存放各个信号量的初始值。 三、实验要求 用三种方法解决 5 个哲学家进餐的问题(利用 fork()创建 5 个子进程,模拟五个哲学家.可 参照课间列出的三种方法和实验指导实验六中的参考代码.) 四、实验步骤 方法一:Sy41.c: #include #include #include union semun{ int val; struct semid_ds *buf; unsigned short *array; struct seminfo *_buf; }arg; int semid; philosopher(int i){ struct sembuf sbuf[2]; sbuf[0].sem_num=i; sbuf[0].sem_flg=SEM_UNDO; sbuf[1].sem_num=(i+1)%5; sbuf[1].sem_flg=SEM_UNDO; while(1){
printf("philosopher %d is thinking\n",i); sleep(2); printf("philosopher %d is hungry\n",i); sbuf[0].sem_op=-1; sbuf[1].sem_op=-1; semop(semid,sbuf,2); printf("philosopher %d is eating\n",i); sleep(2); sbuf[0].sem_op=1; sbuf[1].sem_op=1; semop(semid,sbuf,2); } } main() { int semid,key,pid,status,i; key=ftok("fname",1); semid=semget(key,5,IPC_CREAT|0666); arg.val=1; for(i=0;i<5;i++){ semctl(semid,i,SETVAL,arg); } for(i=0;i<5;i++){ pid=fork(); if(pid==0){ philosopher(i); } } pid=wait(&status); }
方法二:Sy43.c: #include #include #include #include #include #include //筷子作为 mutex pthread_mutex_t chopstick[6] ; void *eat_think(void *arg) { char phi = *(char *)arg; int left,right; //左右筷子的编号 switch (phi){ case 'A': left = 5; right = 1; break; case 'B': left = 1; right = 2; break; case 'C': left = 2; right = 3;
break; case 'D': left = 3; right = 4; break; case 'E': left = 4; right = 5; break; } int i; for(;;){ sleep(3); //思考 pthread_mutex_lock(&chopstick[left]); //拿起左手的筷子 printf("Philosopher %c fetches chopstick %d\n", phi, left); if (pthread_mutex_trylock(&chopstick[right]) == EBUSY){ //拿起右手的筷子 pthread_mutex_unlock(&chopstick[left]); //如果右边筷子被拿走放下左手的筷 子 continue; } // pthread_mutex_lock(&chopstick[right]); //拿起右手的筷子,如果想观察死锁,把上 一句 if 注释掉,再把这一句的注释去掉 printf("Philosopher %c fetches chopstick %d\n", phi, right); printf("Philosopher %c is eating.\n",phi); sleep(3); //吃饭 pthread_mutex_unlock(&chopstick[left]); //放下左手的筷子 printf("Philosopher %c release chopstick %d\n", phi, left); pthread_mutex_unlock(&chopstick[right]); //放下左手的筷子 printf("Philosopher %c release chopstick %d\n", phi, right); } } int main(){ pthread_t A,B,C,D,E; //5 个哲学家 int i; for (i = 0; i < 5; i++) pthread_mutex_init(&chopstick[i],NULL); pthread_create(&A,NULL, eat_think, "A"); pthread_create(&B,NULL, eat_think, "B"); pthread_create(&C,NULL, eat_think, "C"); pthread_create(&D,NULL, eat_think, "D");
pthread_create(&E,NULL, eat_think, "E"); pthread_join(A,NULL); pthread_join(B,NULL); pthread_join(C,NULL); pthread_join(D,NULL); pthread_join(E,NULL); return 0; } 方法三:Sy45.c: #include #include #include #include #include #define phi_num 5 #define think_time 2 #define eat_time 1 #define left (phi_id+phi_num-1)%phi_num #define right (phi_id+1)%phi_num enum { think , hungry , eat } phi_state[phi_num]; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t state[phi_num]={PTHREAD_MUTEX_INITIALIZER}; void Do_think(int phi_id){ printf(" philosopher %d is thinking now !\n",phi_id);
sleep(think_time); } void Do_eat(int phi_id){ printf("philosopher %d is eating now !\n",phi_id); sleep(eat_time); } void check_phi_state(int phi_id){ if(phi_state[phi_id]==hungry&&phi_state[left]!=eat&&phi_state[right]!=eat){ phi_state[phi_id]=eat; pthread_mutex_unlock(&state[phi_id]); } } void Do_take_forks(int phi_id){ pthread_mutex_lock(&mutex); phi_state[phi_id]=hungry; check_phi_state(phi_id); pthread_mutex_unlock(&mutex); pthread_mutex_lock(&state[phi_id]); } void Do_put_forks(int phi_id){ pthread_mutex_lock(&mutex); phi_state[phi_id]=think; check_phi_state(left); check_phi_state(right); pthread_mutex_unlock(&mutex); } void *philosopher(void *arg){ int phi_id=*(int *)arg; while(1){ Do_think(phi_id); Do_take_forks(phi_id); Do_eat(phi_id); Do_put_forks(phi_id); } return NULL; } int main(int argc, char *argv[]){ int num; pthread_t *phi=(pthread_t*)malloc(sizeof(pthread_t)*phi_num); int *id=(int *)malloc(sizeof(int)*phi_num); for(num=0;num
分享到:
收藏