1、操作系统专业课程设计报告格式江苏大学计算机学院课程设计报告课程名称 操作系统课程设计 实验学期 2010至2011学年,第 1 学期学生姓名 周勇 专业班级 计算机0801 学 号 指导教师 詹 永 照 开 课 系 计算机科学系 操作系统课程组制操作系统课程设计报告实验题目:Linux系统管理实践与进程控制、进程通信实现设计时间:2010-12-27至 2011-01-02一、 实验目的与要求1、 掌握基本的同步与互斥算法。2、 学习使用Linux中基本的同步对象,掌握相关函数的使用方法。3、 了解Linux中多进程的并发执行机制,实现进程的同步与互斥。4、 查阅相关资料。5、 熟悉各种命令、
2、系统调用与实用程序。6、 按给定功能设计相关程序。7、 撰写课程设计报告。二、 实验内容桌上有一只盘子,盘子只能放5只水果,每次只能放一只水果或取出一只水果。爸爸专放苹果,妈妈专放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果。分别用P,V操作实现他们的协作行为。三、 实验设备与环境实验设备:虚拟机运行平台:Linux 语言:c四、 设计正文(包括分析与设计思路、各模块流程图以及带注释的 主要算法源码)设计思路:设计4个进程,分别是父亲进程,母亲进程,儿子进程,女儿进程。设置一个缓冲区,用来放水果,长度为5.所以设置一个公有信号量mutex,以限制他们对缓冲区的放和取,初值为1.另外设置
3、私有信号S2,S1.以控制儿子是否可以取橘子吃,女儿是否可以取苹果吃。初值都为0.还要设置一个信号量empty,控制父亲跟母亲之间的同步,初值为5。表示现在缓冲区有5个空位可以放。各模块流程图:Conntrol.c开辟共享存储区设置信号量结构创建信号量:1个用于对缓冲区互斥,3个用于父亲、母亲、儿子、女儿同步释放缓冲区,同时释放信号量给信号量赋初值Father.c 和 mother.c执行P(semid_empty)将进程插入到等待信号量mutex的进程队列中。并且阻塞该进程。empty0将进程插入到等待信号量empty的进程队列中。并且阻塞该进程。执行P(semid_mutex)mutex
4、0 y n y n n 母亲放一个橘子父亲放一个苹果 离开缓冲区执行V(semid_s1)唤醒等待S1进程队列的一个进程。 执行V(semid_mutex),允许母亲放水果,子女取水果。Son.c 执行P(semid_s2)将进程插入到等待信号量mutex的进程队列中。并且阻塞该进程。S20将进程插入到等待信号量s2的进程队列中。并且阻塞该进程。执行P(semid_mutex)mutex 0执行V(semid_empty)唤醒等待empty进程队列的一个进程。 执行V(semid_mutex),允许父母放水果,女儿取苹果。儿子吃一个橘子离开缓冲区 y n y ndaughter.c 执行P(s
5、emid_s1)将进程插入到等待信号量mutex的进程队列中。并且阻塞该进程。S10将进程插入到等待信号量s1的进程队列中。并且阻塞该进程。执行P(semid_mutex)mutex 0执行V(semid_empty)唤醒等待empty进程队列的一个进程。 执行V(semid_mutex),允许父母放水果,儿子取橘子。女儿吃一个苹果离开缓冲区带注释的 主要算法源码:1.Conntrol.c#include #include #include #include #include #include #include #include #define SHMKEY 9075 /*共享存储区的键*/#
6、define SEMKEY_EMPTY 9085#define SEMKEY_S1 9086#define SEMKEY_S2 9087#define SEMKEY_MUTEX 9088 /*信号量数组的键*/#define BUFF_LEN 5 /*缓冲区可以存放个水果*/#define FRUIT_LEN 12 /*水果用字符串代替*/void set_sembuf_struct(struct sembuf *sem,int semnum, int semop,int semflg) /* 设置信号量结构*/ sem-sem_num=semnum; sem-sem_op=semop; se
7、m-sem_flg=semflg; main() char *addr, end; int shmid; unsigned char in; int semid_empty, semid_s1,semid_s2, semid_mutex;/*信号量id*/ struct sembuf sem_tmp; /*开辟共享存储区*/ if (shmid = shmget(SHMKEY, BUFF_LEN * FRUIT_LEN, 0777|IPC_CREAT|IPC_EXCL) = -1) if (errno = EEXIST) printf(The Buffer Has Existed!n); pr
8、intf(Do You Want To Delete The Buffer(Y = yes)?n=:); scanf(%c, &end); if(end = y | end = Y) /* 共享存储区、信号量并不随程序的结束而被删除,如果我们没删除的话, 可以用ipcs命令查看,用ipcrm删除 */ /*释放缓冲区*/ shmid = shmget(SHMKEY, BUFF_LEN * FRUIT_LEN, 0777); if (shmctl(shmid,IPC_RMID,0) 0) perror(shmctl:); /*同时释放信号量*/ semid_mutex = semget(SEMK
9、EY_MUTEX,1, 0777); semid_empty = semget(SEMKEY_EMPTY,1, 0777); semid_s1 = semget(SEMKEY_S1,1, 0777); semid_s2 = semget(SEMKEY_S2,1, 0777); semctl(semid_mutex,0,IPC_RMID); semctl(semid_empty,0,IPC_RMID); semctl(semid_s1,0,IPC_RMID); semctl(semid_s2,0,IPC_RMID); else printf(Fail To Create Buffer!n); r
10、eturn -1; addr = (char*)shmat(shmid, 0, 0);/*连接缓冲区*/ memset(addr, 0, BUFF_LEN * FRUIT_LEN); shmdt(addr); /*离开缓冲区*/ /*创建信号量:1个用于对缓冲区互斥,3个用于父亲、母亲、儿子、女儿同步*/ if(semid_mutex = semget(SEMKEY_MUTEX,1, 0777|IPC_CREAT|IPC_EXCL)=-1) if (errno = EEXIST) printf(The SEMKEY_MUTEX Has Existed!n); else printf(Fail
11、To Create SEMKEY_MUTEX!n); return -1; if(semid_s1 = semget(SEMKEY_S1,1, 0777|IPC_CREAT|IPC_EXCL)=-1) if (errno = EEXIST) printf(The SEMKEY_S1 Has Existed!n); else printf(Fail To Create SEMKEY_S1!n); return -1; if(semid_s2 = semget(SEMKEY_S2,1, 0777|IPC_CREAT|IPC_EXCL)=-1) if (errno = EEXIST) printf(
12、The SEMKEY_S2 Has Existed!n); else printf(Fail To Create SEMKEY_S2!n); return -1; if(semid_empty = semget(SEMKEY_EMPTY,1, 0777|IPC_CREAT|IPC_EXCL)=-1) if (errno = EEXIST) printf(The SEM_EMPTY Has Existed!n); else printf(Fail To Create SEM_EMPTY!n); return -1; /*给信号量赋初值*/ set_sembuf_struct(&sem_tmp,
13、0, BUFF_LEN, 0);/*BUFF_LEN*/ semop(semid_empty, &sem_tmp,1); set_sembuf_struct(&sem_tmp, 0, 0, 0);/*0*/ semop(semid_s1, &sem_tmp,1); set_sembuf_struct(&sem_tmp, 0, 0, 0);/*0*/ semop(semid_s2, &sem_tmp,1); set_sembuf_struct(&sem_tmp, 0, 1, 0);/*1*/ semop(semid_mutex, &sem_tmp,1); return 0;2.Father.c/
14、*下面的P,V是对系统调用的简单封装*/int P(int semid) struct sembuf p_buf; p_buf.sem_num = 0; p_buf.sem_op = -1; p_buf.sem_flg = 0; if(semop(semid, &p_buf, 1)=-1)/*semop参见课件ppt*/ perror (p (semid) falsed); exit (1); else return (0);int V(int semid) struct sembuf v_buf;/*struct sembuf 参见课件ppt*/ v_buf.sem_num = 0; v_b
15、uf.sem_op = 1; v_buf.sem_flg = 0; if(semop(semid, &v_buf, 1)=-1) perror ( v (semid) failed); exit (1); else return (0);main() char *p_buffer;/*共享存储区地址*/ unsigned char in;/*生产者存放产品的指针:它的值存放在全局缓冲区第一个字节*/ int shmid;/*共享存储区id*/ int semid_empty, semid_s1,semid_s2, semid_mutex;/*信号量集合id*/ shmid = shmget(S
16、HMKEY, BUFF_LEN *FRUIT_LEN, 0777);/*连接共享存储区:2 存放in,out的值*/ p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/ semid_mutex = semget(SEMKEY_MUTEX,1, 0777);/*获取全局信号量id*/ semid_empty = semget(SEMKEY_EMPTY,1, 0777); semid_s1 = semget(SEMKEY_S1,1, 0777); semid_s2 = semget(SEMKEY_S2,1, 0777); /*进入临界区*/ P(se
17、mid_empty);/*对私有信号量作P操作*/ P(semid_mutex);/*对公有信号量作P操作*/*二者顺序不能换*/ in = (unsigned char)(*p_buffer); int j=0; for(j=0;j5;j+) if(*(p_buffer + in * FRUIT_LEN)!=apple)&(*(p_buffer + in * FRUIT_LEN)!=orange) printf(father put a apple!n); *(p_buffer + in * FRUIT_LEN)= apple; break; in = (in + 1) % BUFF_LEN
18、; shmdt(p_buffer); /*离开缓冲区*/ /*离开临界区*/ V(semid_s1); V(semid_mutex);3.Mother.c/*下面的P,V是对系统调用的简单封装*/int P(int semid) struct sembuf p_buf; p_buf.sem_num = 0; p_buf.sem_op = -1; p_buf.sem_flg = 0; if(semop(semid, &p_buf, 1)=-1)/*semop参见课件ppt*/ perror (p (semid) falsed); exit (1); else return (0);int V(i
19、nt semid) struct sembuf v_buf;/*struct sembuf 参见课件ppt*/ v_buf.sem_num = 0; v_buf.sem_op = 1; v_buf.sem_flg = 0; if(semop(semid, &v_buf, 1)=-1) perror ( v (semid) failed); exit (1); else return (0);main() char *p_buffer;/*共享存储区地址*/ unsigned char in;/*生产者存放产品的指针:它的值存放在全局缓冲区第一个字节*/ int shmid;/*共享存储区id*
20、/ int semid_empty, semid_s1,semid_s2, semid_mutex;/*信号量集合id*/ shmid = shmget(SHMKEY, BUFF_LEN * FRUIT_LEN, 0777);/*连接共享存储区:2 存放in,out的值*/ p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/ semid_mutex = semget(SEMKEY_MUTEX,1, 0777);/*获取全局信号量id*/ semid_empty = semget(SEMKEY_EMPTY,1, 0777); semid_s1 =
21、semget(SEMKEY_S1,1, 0777); semid_s2 = semget(SEMKEY_S2,1, 0777); /*进入临界区*/ P(semid_empty);/*对私有信号量作P操作*/ P(semid_mutex);/*对公有信号量作P操作*/*二者顺序不能换*/ in = (unsigned char)(*p_buffer); int j=0; for(j=0;j5;j+) if(*(p_buffer + in * FRUIT_LEN)!=apple)&(*(p_buffer + in * FRUIT_LEN)!=orange) printf(mother put a
22、 orange!n); *(p_buffer + in * FRUIT_LEN)= orange; break; in = (in + 1) % BUFF_LEN; shmdt(p_buffer); /*离开缓冲区*/ /*离开临界区*/ V(semid_s2); V(semid_mutex);4.Son.c/*下面的P,V是对系统调用的简单封装*/int P(int semid) struct sembuf p_buf; p_buf.sem_num = 0; p_buf.sem_op = -1; p_buf.sem_flg = 0; if(semop(semid, &p_buf, 1)=-1
23、)/*semop参见课件ppt*/ perror (p (semid) falsed); exit (1); else return (0);int V(int semid) struct sembuf v_buf;/*struct sembuf 参见课件ppt*/ v_buf.sem_num = 0; v_buf.sem_op = 1; v_buf.sem_flg = 0; if(semop(semid, &v_buf, 1)=-1) perror ( v (semid) failed); exit (1); else return (0);main() char *p_buffer;/*共
24、享存储区地址*/ unsigned char in;/*生产者存放产品的指针:它的值存放在全局缓冲区第一个字节*/ int shmid;/*共享存储区id*/ int semid_empty, semid_s1,semid_s2, semid_mutex;/*信号量集合id*/ shmid = shmget(SHMKEY, BUFF_LEN * FRUIT_LEN, 0777);/*连接共享存储区:2 存放in,out的值*/ p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/ semid_mutex = semget(SEMKEY_MUTEX,
25、1, 0777);/*获取全局信号量id*/ semid_empty = semget(SEMKEY_EMPTY,1, 0777); semid_s1 = semget(SEMKEY_S1,1, 0777); semid_s2 = semget(SEMKEY_S2,1, 0777); /*进入临界区*/ P(semid_s2);/*对私有信号量作P操作*/ P(semid_mutex);/*对公有信号量作P操作*/*二者顺序不能换*/ in = (unsigned char)(*p_buffer); int j=0; printf(son get a orange!n); for(j=0;j5
26、;j+) if(*(p_buffer + in * FRUIT_LEN)=orange) *(p_buffer + in * FRUIT_LEN)=0; break; in = (in + 1) % BUFF_LEN; shmdt(p_buffer); /*离开缓冲区*/ /*离开临界区*/ V(semid_empty); V(semid_mutex);5.Daughter.c/*下面的P,V是对系统调用的简单封装*/int P(int semid) struct sembuf p_buf; p_buf.sem_num = 0; p_buf.sem_op = -1; p_buf.sem_flg
27、 = 0; if(semop(semid, &p_buf, 1)=-1)/*semop参见课件ppt*/ perror (p (semid) falsed); exit (1); else return (0);int V(int semid) struct sembuf v_buf;/*struct sembuf 参见课件ppt*/ v_buf.sem_num = 0; v_buf.sem_op = 1; v_buf.sem_flg = 0; if(semop(semid, &v_buf, 1)=-1) perror ( v (semid) failed); exit (1); else r
28、eturn (0);main() char *p_buffer;/*共享存储区地址*/ unsigned char in;/*生产者存放产品的指针:它的值存放在全局缓冲区第一个字节*/ int shmid;/*共享存储区id*/ int semid_empty, semid_s1,semid_s2, semid_mutex;/*信号量集合id*/ shmid = shmget(SHMKEY, BUFF_LEN * FRUIT_LEN, 0777);/*连接共享存储区:2 存放in,out的值*/ p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/
29、 semid_mutex = semget(SEMKEY_MUTEX,1, 0777);/*获取全局信号量id*/ semid_empty = semget(SEMKEY_EMPTY,1, 0777); semid_s1 = semget(SEMKEY_S1,1, 0777); semid_s2 = semget(SEMKEY_S2,1, 0777); /*进入临界区*/ P(semid_s1);/*对私有信号量作P操作*/ P(semid_mutex);/*对公有信号量作P操作*/*二者顺序不能换*/ in = (unsigned char)(*p_buffer); int j=0; pri
30、ntf(daughter get a apple!n); for(j=0;j5;j+) if(*(p_buffer + in * FRUIT_LEN)=apple) *(p_buffer + in * FRUIT_LEN)=0; break; in = (in + 1) % BUFF_LEN; shmdt(p_buffer); /*离开缓冲区*/ /*离开临界区*/ V(semid_empty); V(semid_mutex);五、 实验结果及分析放入了5个水果,在执行父亲进程,则该进程被阻塞。此时执行儿子进程,吃掉一个橘子,缓冲区空位增1,唤醒了等待中的父亲进程,此时父亲可以放入一个橘子。此
31、时橘子被吃完,再执行儿子进程,则被阻塞。执行一次母亲进程,放入一个橘子,来唤醒儿子进程,此时刚才的儿子进程执行,吃掉一个橘子。缓冲区满,执行母亲进程,被阻塞执行儿子进程,吃掉一个橘子,此时唤醒刚才的母亲进程,放入一个橘子。女儿吃完了苹果,在执行女儿进程,则被阻塞。执行父亲进程,增加一个苹果,唤醒刚才等待中的女儿进程,女儿吃掉一个苹果。六、 小结通过此次课程设计,我在网上跟图书馆查找了不少有关linux操作的资料,熟悉了linux操作系统的基本操作命令,以及熟悉了pv操作原理,实现了LINUX系统管理实践与进程控制、进程通信。而且学会了安装linux虚拟机。增强了自己的动手能力,受益匪浅。我觉得
32、比较关键第一步就是怎样做才能在linux下察看到windows下的资源。经过查阅相关资料,我这里就采用了Linux下smb服务共享方法。应用Samba技术并不是唯一的解决网络资源共享的方法。像Xlink公司的Omni-NFS也能实现网络文件和打印机资源的共享。就性能而言,SMB和NFS不相上下。Samba的最大优点就是其为源代码开放的自由软件,更新迅速,移植方便。大体步骤:1.建立Samba帐户,编辑帐户文件,删除不需要的帐户。2.利用smbpasswd命令建立帐户的口令,最好与/etc/passwd的帐户口令相同。3.编辑/etc/smb.conf文件,修改global段的4.重新启动SMB
33、服务,再进行测试。#serives smbrestart。.然后就可以在linux操作系统下可以完成进程通信。其次还要设置好互斥同步信号量,不能少。一开始先看了老师的程序,有些不清楚的地方也问了研究生,研究生也很负责的讲解了。后来自己按照老师的模版进行反复修改,检验。一开始程序比较冗余,不简洁,经过同学老师的指导,删掉了一些没必要的东西。在执行时候一开始也不知道可以开两个或更多的终端来检查通讯是否正确。经过别人提醒才知道,这样就可以很清楚的看到阻塞中的进程被唤醒,一目了然。总之,这次课程设计很有收获,不仅会自己安装虚拟机,也懂了如何在linux下共享windows下的资源,也自学部分linux操作命令和在linux下进行进程通信,实现了进程的同步与互斥。一些指令自己也可以熟练的打出来。课程中遇到的问题会合理的解决,学习到了很多。我觉得我应该继续学习些linux或者其他计算机方面有关的知识,为以后课设或者学习打下基础。七、 参考文献操作系统原理 鞠时光主编 武汉理工大学出版社LINUX操作系统之奥秘邱世华著 电子工业出版Linux命令详解词典 施威铭研究室著 机械工业出版Linux编程从入门到精通宫虎波著 化学工业出版成 绩: 教师签名: 年 月 日