操作系统实验

您所在的位置:网站首页 linux进程操作实验报告 操作系统实验

操作系统实验

2023-07-06 03:11| 来源: 网络整理| 查看: 265

一、实验目的:

(1)实现哲学家就餐问题,要求不能出现死锁。

(2)通过本实验熟悉Linux系统的基本环境,了解Linux下进程和线程的实现。

二、实验原理:

(1)问题描述:五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取其左右最靠近它的筷子,只有他拿到两只筷子时才能进餐。进餐毕,放下筷子继续思考。

(2)拿起筷子和放下筷子的操作如何实现:筷子是临界资源,拿起筷子操作就哲学家(不同任务)之间是对临界资源的互斥访问,放下筷子就是对临界资源的释放,在Linux中可以通过多种机制来实现:

1)互斥量(加锁,解锁),适用于线程

2)POSIX信号量(P操作,V操作),无名信号量适用于线程,命名信号量适用于进程/线程

3)XSI信号量集(P操作,V操作),同时适用于进程与线程

(3)预防死锁的实现方法:破坏“循环等待条件”,对哲学家编号,奇偶号哲学家拿起筷子的顺序不同。规定:奇数编号哲学家先拿左边筷子再拿右边筷子,偶数编号哲学家先拿右边筷子再拿左边筷子。

(4)避免死锁的实现方法:再创建一个任务,哲学家拿起筷子时向该任务发起申请,由该任务对当前筷子的分配情况进行判断,判定系统是否由安全状态向不安全状态转换,从而允许或拒绝该次申请

三、实验内容:

(1)在linux系统下实现教材2.5.2节中所描述的哲学家就餐问题。要求显示出每个哲学家的工作状态,如吃饭,思考。连续运行30次以上都未出现死锁现象。

(2)熟悉Ubuntu系统下的多线程编程。

1)使用“Ctrl+Alt+T”打开终端;

2)使用gedit或vim命令打开文本编辑器进行编码 “gedit 文件名.c”

3)编译程序: “gcc 文件名.c -o 可执行程序名”(如果只输入gcc 文件名.c,默认生成可执行程序名为a.out)使用线程库时,gcc编译需要添加-lpthread

4)执行程序:./可执行程序名

四、实验器材(设备、元器件):

学生每人一台PC,安装Windows8操作系统。个人PC安装VMware虚拟机和Ubuntu系统。

五、实验步骤:

(1)在Ubuntu系统中使用“Ctrl+Alt+T”打开终端;

(2)使用vim命令打开文本编辑器进行编码 “vim lab1.c”

(3)编写lab.c源程序实现哲学家就餐问题

(4)编译程序:“gcc lab1.c -o test”

(5)执行程序:./test

六、具体代码

        为解决哲学家就餐问题中出现死锁的情况,从0开始依次对每个哲学家进行编号,并规定:奇数编号哲学家先拿左边筷子再拿右边筷子,偶数编号哲学家先拿右边筷子再拿左边筷子,这样就不会出现死锁现象了,奇偶编号预防死锁发生代码如下所示:

#include #include #include #include // 利用互斥量实现哲学家就餐问题 //规定奇数哲学家先拿左边筷子再拿右边筷子,偶数哲学家先拿右边筷子再拿左边筷子 pthread_mutex_t chopstick[5]; // 定义互斥量 void *func(void*);// 线程函数 void init(); int main(){ init();//初始化互斥量 pthread_t p1,p2,p3,p4,p5; // 定义哲学家 pthread_create(&p1,NULL,func,"0"); pthread_create(&p2,NULL,func,"1"); pthread_create(&p3,NULL,func,"2"); pthread_create(&p4,NULL,func,"3"); pthread_create(&p5,NULL,func,"4"); pthread_join(p1,NULL); pthread_join(p2,NULL); pthread_join(p3,NULL); pthread_join(p4,NULL); pthread_join(p5,NULL); return 0; } void init(){ int i = 0; for(;i < 5; i++){ chopstick[i] = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; } } void *func(void *arg){ int i = 0; int num = atoi((char *)arg); do{ printf("哲学家%d正在思考\n",num + 1); sleep(1); if(num % 2 == 0){ //偶数哲学家 pthread_mutex_lock(&chopstick[(num + 1) % 5]); pthread_mutex_lock(&chopstick[num]); printf("哲学家%d正在就餐\n",num + 1); sleep(1); pthread_mutex_unlock(&chopstick[(num + 1) % 5]); pthread_mutex_unlock(&chopstick[num]); } else{ //奇数哲学家 pthread_mutex_lock(&chopstick[num]); pthread_mutex_lock(&chopstick[(num + 1) % 5]); printf("哲学家%d正在就餐\n",num + 1); sleep(1); pthread_mutex_unlock(&chopstick[num]); pthread_mutex_unlock(&chopstick[(num + 1) % 5]); } i++; } while(i < 30); }

七、总结及心得体会:

        通过本次实验,我熟悉了Linux系统的基本环境,了解了如何在Linux下实现线程的创建、终止以及互斥量的初始化、上锁、解锁、销毁。同时也能够利用Linux的线程、互斥量机制实现哲学家就餐问题,并且知道了如何能够是程序不出现死锁现象。

八、对本实验过程及方法、手段的改进建议:

        本实验也可使用破坏“请求和保持条件”的方法来使得程序不出现死锁,即哲学家如果无法同时拿起两支筷子,则放下已经拿起的筷子,等待一段时间再尝试,利用POSIX API中的非阻塞操作pthread_mutex_trylock实现对能否拿起筷子的判断。相较于为每个哲学家编号,上述方法更容易理解与实现,破坏请求和保持条件预防死锁代码如下所示:

#include #include #include #include // 利用互斥量实现哲学家就餐问题 pthread_mutex_t chopstick[5]; // 定义互斥量 void *philosopher1(void);// 哲学家1 void *philosopher2(void);// 哲学家2 void *philosopher3(void);// 哲学家3 void *philosopher4(void);// 哲学家4 void *philosopher5(void);// 哲学家5 void init(); int main(){ init();//初始化互斥量 pthread_t p1,p2,p3,p4,p5; pthread_create(&p1,NULL,(void*)philosopher1,NULL); pthread_create(&p2,NULL,(void*)philosopher2,NULL); pthread_create(&p3,NULL,(void*)philosopher3,NULL); pthread_create(&p4,NULL,(void*)philosopher4,NULL); pthread_create(&p5,NULL,(void*)philosopher5,NULL); pthread_join(p1,NULL); pthread_join(p2,NULL); pthread_join(p3,NULL); pthread_join(p4,NULL); pthread_join(p5,NULL); } void init(){ int i = 0; for(;i < 5; i++){ chopstick[i] = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; } } void *philosopher1(void){ int i = 0; do{ printf("哲学家1正在思考\n"); sleep(1); pthread_mutex_trylock(&chopstick[0]); if(pthread_mutex_trylock(&chopstick[1]) != 0){ pthread_mutex_unlock(&chopstick[0]); continue; } printf("哲学家1正在就餐\n"); sleep(1); pthread_mutex_unlock(&chopstick[0]); pthread_mutex_unlock(&chopstick[1]); i++; } while(i < 30); } void *philosopher2(void){ int i = 0; do{ printf("哲学家2正在思考\n"); sleep(1); pthread_mutex_trylock(&chopstick[1]); if(pthread_mutex_trylock(&chopstick[2]) != 0){ pthread_mutex_unlock(&chopstick[1]); continue; } printf("哲学家2正在就餐\n"); sleep(1); pthread_mutex_unlock(&chopstick[1]); pthread_mutex_unlock(&chopstick[2]); i++; } while(i < 30); } void *philosopher3(void){ int i = 0; do{ printf("哲学家3正在思考\n"); sleep(1); pthread_mutex_trylock(&chopstick[2]); if(pthread_mutex_trylock(&chopstick[3]) != 0){ pthread_mutex_unlock(&chopstick[2]); continue; } printf("哲学家3正在就餐\n"); sleep(1); pthread_mutex_unlock(&chopstick[2]); pthread_mutex_unlock(&chopstick[3]); i++; } while(i < 30); } void *philosopher4(void){ int i = 0; do{ printf("哲学家4正在思考\n"); sleep(1); pthread_mutex_trylock(&chopstick[3]); if(pthread_mutex_trylock(&chopstick[4]) != 0){ pthread_mutex_unlock(&chopstick[3]); continue; } printf("哲学家4正在就餐\n"); sleep(1); pthread_mutex_unlock(&chopstick[3]); pthread_mutex_unlock(&chopstick[4]); i++; } while(i < 30); } void *philosopher5(void){ int i = 0; do{ printf("哲学家5正在思考\n"); sleep(1); pthread_mutex_trylock(&chopstick[4]); if(pthread_mutex_trylock(&chopstick[0]) != 0){ pthread_mutex_unlock(&chopstick[4]); continue; } printf("哲学家5正在就餐\n"); sleep(1); pthread_mutex_unlock(&chopstick[4]); pthread_mutex_unlock(&chopstick[0]); i++; } while(i < 30); }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3