长春理工大学 软件学院 0813111班 27号
姓名:丁为胜 一. 概述
1、课程设计目的及任务课程设计地点及要求
每个学生一台微机,需要安装windows98或windows2000操作系统,配备VC、VB、java或C编程语言,每个学生上机时间不少于24个小时。
操作系统是计算机专业的核心专业课,“操作系统课程设计”是理解和巩固操作系统基本理论、原理和方法的重要的实践环节。
操作系统课程主要讲述的内容是多道操作系统的原理与技术,与其它计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分密切。本课程设计的目的综合应用学生所学知识,建立系统和完整的计算机系统概念,理解和巩固操作系统基本理论、原理和方法,掌握操作系统基本理论与管理方式。在算法基础上,解决实际的管理功能的问题,提高学生实际应用、编程的能力。
主要任务是实现操作系统和相关系统软件的设计,其中涉及进程创建,同步,进程间的通信,存储管理,文件系统等操作系统概念。
2.课程设计地点及要求
每个学生一台微机,需要安装windows98或windows2000操作系统,配备VC、VB、java或C编程语言,每个学生上机时间不少于24个小时。
3.课程设计的内容
设计二: 设计任务:
掌握进程的管道通讯机制和信号量同步互斥机制。 1. 进程的管道通讯
编制一个程序,程序中创建一个子进程。然后父子进程各自独立运行,父进程不断地在标准输入设备上读入小写字母,写入管道。子进程不断地从管道中读取字符,转换为大写字母后输出到标准输出设备上。当读到x时,结束。
2. 信号量实现的同步互斥机制
编制一个程序,程序中创建5个子进程,代表五位哲学家,然后父进程结束。使用信号量机制解决哲学家进餐问题。当哲学家进餐时,屏幕输出:
[进程号] eating! 当哲学家思考时,屏幕输出: [进程号] thinging! 相关的系统调用和函数:pipe(); write(); read(); semget(); sepop(); semctl(); 要求:查找并阅读上述系统调用的相关资料,将上述相关的函数封装为P( )、V( )操作,使用你封装的P( )、V( )操作实现5位哲学家的同步和互斥。
二. 设计的基本概念和原理
1.进程的管道通讯
管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。命名管道(Named Pipes)是在管道服务器和一台或多台管道客户机之间进行单向或双向通信的一种命名的管道。一个命名管道的所有实例共享同一个管道名,但是每一个实例均拥有独立的缓存与句柄,并且为客户——服务通信提供有一个分离的管道。实例的使用保证了多个管道客户能够在同一时间使用同一个命名管道。
2.信号量实现的同步互斥机制
规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号 的哲学家则相反.按此规定,将是1,2号哲学家竞争1号筷子,3,4号哲学家竞争3号筷子.即 五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获 得两支筷子而进餐。而申请不到的哲学家进入阻塞等待队列,根FIFO原则,则先申请的哲 学家会较先可以吃饭,因此不会出现饿死的哲学家。
三. 总体设计
1.实现的方法和主要技术路线
1.无名管道
无名管道用于具有亲缘关系的父子进程,子子进程之间的通讯。它的实现函数有 int pipe(int fd[2]);
//fd[2] 为描述符数组,包含一个读描述符与一个写描述符,在使用管道通信时,关闭某些不需要的读或写描述符,建立起单向的读或写管道,然后用read 和write 像操作文件一样去操作它即可。
如图便是进程1 到进程2 的一个读管道。
分别在父进程和父子进程里向管道写数据,然后在子进程和子子进程里读数据。 2.哲学家进餐伪码:
semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int i) {
while(true) {
think();
if(i%2 == 0) //偶数哲学家,先右后左。
{
wait (chopstick[ i + 1 ] mod 5) ; wait (chopstick[ i]) ; eat();
signal (chopstick[ i + 1 ] mod 5) ; signal (chopstick[ i]) ; }
Else //奇数哲学家,先左后右。
{
wait (chopstick[ i]) ;
wait (chopstick[ i + 1 ] mod 5) ; eat();
signal (chopstick[ i]) ;
signal (chopstick[ i + 1 ] mod 5) ; } } 四. 详细设计
进程的管道通信代码: import java.io.IOException; import java.io.PipedReader;
public cla ReceiverThread1 extends Thread { PipedReader pipedReader;
public ReceiverThread1(SenderThread1 sender) throws IOException
{
pipedReader=new PipedReader(sender.getPipedWriter());
}
public void run()
{ char[] ch=new char[100]; StringBuffer sb=null; String str=null; int i=0; try {
while((i=pipedReader.read(ch))!=-1)
{
sb=new StringBuffer();
for(int j=0;j
{
sb.append(ch[j]);
}
str=sb.toString();
System.out.println(\"子进程读取的字符为:\"+str.toUpperCase());
if(!str.endsWith(\"x\"))
{
System.out.print(\"父进程读入字符为:\");
}else if(str.endsWith(\"x\"))
{
System.out.println(\"结束无法再次输入字符\");
}
} } catch (IOException e) {
e.printStackTrace(); }finally{
try {
pipedReader.close();
} catch (IOException e) {
e.printStackTrace();
} }
}
}
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PipedWriter;
public cla SenderThread1 extends Thread { PipedWriter pipedWriter;
public SenderThread1() {
pipedWriter=new PipedWriter(); }
public PipedWriter getPipedWriter() {
return pipedWriter; }
public void run()
{ BufferedReader ir=new BufferedReader(new InputStreamReader(System.in)); char[] ch=new char[100]; StringBuffer sb=null; String str=null; int i=0; System.out.print(\"父进程读入字符为:\"); try {
while((i=ir.read(ch))!=-1)
{
sb=new StringBuffer();
for(int j=0;j
{
if(ch[j]>=\'a\' && ch[j]
{
sb.append(ch[j]);
if(ch[j]==\'x\')
{
break;
}
}
}
str=sb.toString();
pipedWriter.write(str);
if(str.startsWith(\"x\")||str.endsWith(\"x\"))
{
break;
// this.stop();
}
}
} catch (IOException e) {
e.printStackTrace(); }finally{
try {
ir.close();
pipedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
public cla ThreadComm1 { public static void main(String[] args)throws Exception{ SenderThread1 sender=new SenderThread1(); ReceiverThread1 receiver=new ReceiverThread1(sender); sender.start(); receiver.start(); } } 哲学家进餐问题代码: #include \"stdafx.h\" using namespace std; bool chop[100];//定义筷子 cla ph { protected: bool * left,* right;//哲学家的左右手指向的筷子
int eattime;//哲学家的吃饭时间 public: bool check()//用于检查哲学家左右手的筷子是不是被占用
{
if(*left && *right)
return true;
else
return false; } void eat(int ineattime)//哲学家开始进餐
{
eattime=ineattime;
*left=false;
*right=false; } bool finish()//检查哲学家是否完成进餐
{
if(eattime>0)//没完成的话剩余时间减少
{
eattime--;
if(eattime==0)//完成的话归还筷子
{
*left=true;
*right=true;
return true;
}
else
return false;
}
else
return false; } void init(int num,int max)//初始化哲学家,指定他们使用的筷子
{
eattime=0;
left=&chop[num];
if(num
right=&chop[num+1];
else
right=&chop[0]; } }; void main() { system(\"title 哲学家进餐问题\"); int in,i,temp,time,j=1; queue Q; ph P[100];
for(int i=0;i
chop[i]=1;
} for(int i=0;i>in; if(in==0)
break; else
if(in>5)
{
cout
}
else
{
Q.push(in-1);
} } cout>time; system(\"CLS\"); system(\"color 0a\"); while(!Q.empty()) { temp=Q.front(); Q.pop(); if(P[temp].check()) {
P[temp].eat(time);
cout
if(temp+2>5)
cout
else
cout
Q.push(temp); } for(i=0;i
{
if(P[i].finish())
cout
}
//Q.push(-1);
for(i=0;i
{
temp=Q.front();
Q.pop();
//if(temp!=-1)
{
cout
Q.push(temp);
}
//else
{
// Q.pop();
break;
}
} } for(int j=0;j
if(P[i].finish())
{
cout
} getch(); }