logo资料库

信号量同步实验报告(哲学家进餐问题避免死锁的三种方法).doc

第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
资料共15页,剩余部分请下载后查看
实验二 进程同步
一、实验目的:
二、实验平台:
三、实验内容:
四、实验总结
实验二 进程同步 一、实验目的: 掌握基本的同步算法,理解经典进程同步问题的本质;学习使用 Linux 的进程同步机制, 掌握相关 API 的使用方法;能利用信号量机制,采用多种同步算法实现不会发生死锁的哲 学家进餐程序。 二、实验平台: 虚拟机:VMware® Workstation 14 Pro 14.1.1 操作系统:Ubuntu 系统版本:Deepin 15.7 内核版本:4.15.0-29deepin-generic 编辑器: Vim 8.0.1766 编译器:Gcc 7.3.0 三、实验内容: (1)以哲学家进餐模型为依据,在 Linux 控制台环境下创建 5 个进程,用 semget 函数 创建一个信号量集(5 个信号量,初值为 1),模拟哲学家的思考和进餐行为:每一位哲学家 饥饿时,先拿起左手筷子,再拿起右手筷子;筷子是临界资源,为每一支筷子定义 1 个互斥 信号量;想拿到筷子需要先对信号量做 P 操作,使用完释放筷子对信号量做 V 操作。 伪代码描述: semaphore chopstick[5]={1,1,1,1,1}; 第 i 位哲学家的活动可描述为: do{ printf("%d is thinking\n",i); printf("%d is hungry\n",i); wait(chopstick[i]); //拿左筷子 wait(chopstick[(i+1) % 5]); //拿右筷子 printf("%d is eating\n",i); signal(chopstick[i]); signal(chopstick[(i+1) % 5]); //放左筷子 //放右筷子
… }while[true]; 运行该组进程,观察进程是否能一直运行下去,若停滞则发生了什么现象?并分析原因。 代码: #include #include #include #include #include #include #include #include #include #include #include #include #ifdef union semun { _SEM_SEMUN_UNDEFINED int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; }; #endif #define ERR_EXIT(m) \ do { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) int wait_1chopstick(int no,int semid) { struct sembuf sb = {no,-1,0}; int ret;
ret = semop(semid,&sb,1); if(ret < 0) { ERR_EXIT("semop"); } return ret; } int free_1chopstick(int no,int semid) { struct sembuf sb = {no,1,0}; int ret; ret = semop(semid,&sb,1); if(ret < 0) { ERR_EXIT("semop"); } return ret; } #define DELAY (rand() % 5 + 1) void wait_for_2chopstick(int no,int semid) { int left = no; int right = (no + 1) % 5; struct sembuf buf[2] = { {left,-1,0}, {right,-1,0} }; semop(semid,buf,2); } void free_2chopstick(int no,int semid) { int left = no; int right = (no + 1) % 5;
struct sembuf buf[2] = { {left,1,0}, {right,1,0} }; semop(semid,buf,2); } void philosophere(int no,int semid) { srand(getpid()); for(;;) { #if 0 printf("%d is thinking\n",no); sleep(DELAY); printf("%d is hungry\n",no); wait_for_2chopstick(no,semid); printf("%d is eating\n",no); sleep(DELAY); free_2chopstick(no,semid); #else int left = no; int right = (no + 1) % 5; printf("%d is thinking\n",no); sleep(DELAY); printf("%d is hungry\n",no); wait_1chopstick(left,semid); sleep(DELAY); wait_1chopstick(right,semid); printf("%d is eating\n",no); sleep(DELAY); free_1chopstick(left,semid); free_1chopstick(right,semid); #endif } }
int main(int argc,char *argv[]) { int semid; semid = semget(IPC_PRIVATE,5,IPC_CREAT | 0666); if(semid < 0) { ERR_EXIT("semid"); } union semun su; su.val = 1; int i; for(i = 0;i < 5;++i) { semctl(semid,i,SETVAL,su); } int num = 0; pid_t pid; for(i = 1;i < 5;++i) { pid = fork(); if(pid < 0) { ERR_EXIT("fork"); } if(0 == pid) { num = i; break; } } philosophere(num,semid); return 0; } 执行结果
实验结果分析: 起初,实验结果一直如图一,会有 semop: Interrupted system call,后通过百度查明原 因 , 是 因 为 信 号 量 中 断 导 致 的 , 于 是 就 在 wait 操 作 上 做 了 些 修 改 , 把 ret = semop(semid,&sb,1 改为 while(ret = semop(semid,&sb,1)&&errno==EINTR);即出现信号 量中断时循环运行,遂解决。
之后的结果如图二所示,出现死锁,具体原因应该是在每个哲学家思考拿了左筷子 之后有一个 sleep()函数使当前进程沉睡,系统调用下一个进程,直至五个哲学家一 人一只筷子,进程死锁。 (2)方法b代码: #include #include #include #include #include #include #include #include #include #include #include #include #ifdef union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; }; #endif #define ERR_EXIT(m) \ do { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) int wait_1chopstick(int no,int semid) { _SEM_SEMUN_UNDEFINED struct sembuf sb = {no,-1,0}; int ret; while(ret = semop(semid,&sb,1)&&errno==EINTR); if(ret < 0) { ERR_EXIT("semop"); } return ret;
} int waitchopstick(int semid) { struct sembuf sb = {5,-1,0}; int ret; while(ret = semop(semid,&sb,1)&&errno==EINTR); if(ret < 0) { ERR_EXIT("semop"); } return ret; } int free_1chopstick(int no,int semid) { struct sembuf sb = {no,1,0}; int ret; ret = semop(semid,&sb,1); if(ret < 0) { ERR_EXIT("semop"); } return ret; } int freechopstick(int semid) { struct sembuf sb = {5,1,0}; int ret; ret = semop(semid,&sb,1); if(ret < 0) { ERR_EXIT("semop"); } return ret; } #define DELAY (rand() % 5 + 1) void wait_for_2chopstick(int no,int semid) { int left = no; int right = (no + 1) % 5; struct sembuf buf[2] = { {left,-1,0}, {right,-1,0} };
分享到:
收藏