操作系统课程设计编程模拟多进程共享临界资源.docx
《操作系统课程设计编程模拟多进程共享临界资源.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计编程模拟多进程共享临界资源.docx(19页珍藏版)》请在冰点文库上搜索。
操作系统课程设计编程模拟多进程共享临界资源
题目:
编程模拟多进程共享临界
资源
班级:
0
姓名:
0
学号:
0
指导教师:
0
2011年12月
综合实践评分表
班级
0
姓名
0
指导教师
0
题目:
编程演示多进程共享临界资源
评分标准
评分标准
分数权重
评分的依据
得分
A
C
选题
10
选题符合大纲要求,题目较新颖,工作量大
选题基本符合大纲要求,工作量适中
工作态度
10
态度端正,能主动认真完成各个环节的工作,不迟到早退,出勤好。
能够完成各环节基本工作,出勤较好。
存储结构、算法描述
20
能正确选择存储结构,定义准确,算法流程图或类C语言描述的算法准确无误
能正确选择存储结构,算法流程图或类C语言描述的算法基本准确
独立解决问题的能力
10
具有独立分析、解决问题能力,有一定的创造性,能够独立完成软件的设计与调试工作,程序结构清晰,逻辑严谨,功能完善。
有一定的分析、解决问题能力。
能够在老师指导下完成软件的设计与调试工作,程序功能较完善。
答辨问题回答
20
能准确回答老师提出的问题
能基本准确回答老师提出的问题
程序运行情况
10
程序运行正确、界面清晰,测试数据设计合理。
程序运行正确、界面较清晰,能给出合适的测试数据。
综合实践报告
20
格式规范,层次清晰,设计思想明确,解决问题方法合理,体会深刻。
格式较规范,设计思想基本明确,解决问题方法较合理。
总分
指导教师(签字):
注:
介于A和C之间为B级,低于C为D级和E级。
按各项指标打分后,总分在90~100为优,80~89为良,70~79为中,60~69为及格,60分以下为不及格。
编程演示多进程共享临界资源
摘要:
一般我们在java中运行其它类中的方法时,无论是静态调用,还是动态调用,都是在当前的进程中执行的,也就是说,只有一个java虚拟机实例在运行。
而有的时候,我们需要通过java代码启动多个java子进程。
这样做虽然占用了一些系统资源,但会使程序更加稳定,因为新启动的程序是在不同的虚拟机进程中运行的,如果有一个进程发生异常,并不影响其它的子进程。
在Java中我们可以使用两种方法来实现这种要求。
最简单的方法就是通过Runtime中的exec方法执行javaclassname。
如果执行成功,这个方法返回一个Process对象,如果执行失败,将抛出一个IOException错误。
关键字:
多进程临界区资源
1,引言
以前古老的DOS操作系统(V6.22)是单任务的,还没有线程的概念,系统在每次只能做一件事情。
比如你在copy东西的时候不能rename文件名。
为了提高系统的利用效率,采用批处理来批量执行任务。
现在的操作系统都是多任务操作系统,每个运行的任务就是操作系统所做的一件事情,比如你在听歌的同时还在用MSN和好友聊天。
听歌和聊天就是两个任务,这个两个任务是“同时”进行的。
一个任务一般对应一个进程,也可能包含好几个进程。
比如运行的MSN就对应一个MSN的进程,如果你用的是windows系统,你就可以在任务管理器中看到操作系统正在运行的进程信息。
一般来说,当运行一个应用程序的时候,就启动了一个进程,当然有些会启动多个进程。
启动进程的时候,操作系统会为进程分配资源,其中最主要的资源是内存空间,因为程序是在内存中运行的。
在进程中,有些程序流程块是可以乱序执行的,并且这个代码块可以同时被多次执行。
实际上,这样的代码块就是线程体。
线程是进程中乱序执行的代码流程。
当多个线程同时运行的时候,这样的执行模式成为并发执行。
多线程的目的是为了最大限度的利用CPU资源。
Java编写程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。
每用java命令启动一个java应用程序,就会启动一个JVM进程。
在同一个JVM进程中,有且只有一个进程,就是它自己。
在这个JVM环境中,所有程序代码的运行都是以线程来运行。
一般常见的Java应用程序都是单线程的。
比如,用java命令运行一个最简单的HelloWorld的Java应用程序时,就启动了一个JVM进程,JVM找到程序程序的入口点main(),然后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。
当main方法结束后,主线程运行完成。
JVM进程也随即退出。
对于一个进程中的多个线程来说,多个线程共享进程的内存块,当有新的线程产生的时候,操作系统不分配新的内存,而是让新线程共享原有的进程块的内存。
因此,线程间的通信很容易,速度也很快。
不同的进程因为处于不同的内存块,因此进程之间的通信相对困难。
实际上,操作的系统的多进程实现了多任务并发执行,程序的多线程实现了进程的并发执行。
多任务、多进程、多线程的前提都是要求操作系统提供多任务、多进程、多线程的支持。
在Java程序中,JVM负责线程的调度。
线程调度是值按照特定的机制为多个线程分配CPU的使用权。
调度的模式有两种:
分时调度和抢占式调度。
分时调度是所有线程轮流获得CPU使用权,并平均分配每个线程占用CPU的时间;抢占式调度是根据线程的优先级别来获取CPU的使用权。
JVM的线程调度模式采用了抢占式模式。
所谓的“并发执行”、“同时”其实都不是真正意义上的“同时”。
众所周知,CPU都有个时钟频率,表示每秒中能执行cpu指令的次数。
在每个时钟周期内,CPU实际上只能去执行一条(也有可能多条)指令。
操作系统将进程线程进行管理,轮流(没有固定的顺序)分配每个进程很短的一段是时间(不一定是均分),然后在每个线程内部,程序代码自己处理该进程内部线程的时间分配,多个线程之间相互的切换去执行,这个切换时间也是非常短的。
因此多任务、多进程、多线程都是操作系统给人的一种宏观感受,从微观角度看,程序的运行是异步执行的。
2,需求分析
要求产生3个进程:
(1)两个进程模拟需要进入临界区的用户进程,当需要进入临界区时,显示:
“进程x请求进入临界区…”,同时向管理进程提出申请;申请返回,表示进入了临界区。
在临界区中等待一段随机时间,并显示:
“进程x正在临界区…”;当时间结束,显示:
“进程x退出临界区…”,同时向管理进程提出退出申请;当申请返回,显示:
“进程x已退出临界区。
”
(2)一个进程作为原语的管理进程,接受其他进程的临界区进入请求:
如果允许进入,则设置相应变量,然后返回;如果不允许进入,则进入循环等待,直到允许为止;
(3)对临界区的访问应遵循空闲让进、忙则等待、有限等待、让权等待的准则。
(4)进程间通信可以采用信号、消息传递、管道或网络通信方式。
3,实现原理
通过编写,创建两个进程模拟需要进入临界区,另外编写一个进程作为原语的管理进程,其负责两个进程的进入!
接着设置一个临界区,让其进程在其中访问遵循空闲让进、忙则等待、有限等待、让权等待的准则。
当进程和临界区建立好后,临界区的数据传输,受到了系统硬件的支持,不耗费多余的资源;而进程间通信传递,由软件进行控制和实现,需要消耗一定的CPU资源。
从这个意义上讲,临界区更适合频繁和大量的数据传输。
进程信息的传递,自身就带有同步的控制。
当等到信息的时候,进程进入睡眠状态,不再消耗CPU资源。
而共享队列如果不借助其他机制进行同步,接收数据的一方必须进行不断的查询,白白浪费了大量的CPU资源。
3,算法实现模型图
图1算法实现模型图
5,算法实现流程图
(1)进程状态转换
进程的状态反映进程执行进程的变化。
这些状态随着进程的执行和外界条件发生变化和转换。
下图给出了有一个基本状态,即就绪状态、执行状态与等待状态之间的转换关系。
图2进程状态转换
(2)PCB的组织方式
PCB的组织方式将处于同一状态的进程组织在一起。
链表:
同一状态的进程其PCB成一链表,多个状态对应多个不同的链表
各状态的进程形成不同的链表:
就绪链表、阻塞链表
索引表:
同一状态的进程归入一个index表(由index指向PCB),多个状态对应多个不同的index表
各状态的进行形成不同的索引表:
就绪索引表、阻塞索引表
图3PCB的组织方式
(3)进程队列
为了实现对进程的管理,系统将所有进程的PCB排成若干个队列,称为进程队列。
(4)唤醒原语
当等待队列中的进程所等待的事件发生时,等待该事件的所有进程都将被唤醒。
显然,一个处于阻塞状态的进程不可能自己唤醒自己(为什么?
)唤醒一个进程有两种方法:
一种是由系统进程唤醒。
另一种是由事件发生进程唤醒。
当由系统进程唤醒等待进程时,系统进程统一控制事件的发生并将“事件发生”这一消息通知等待进程。
从而使得该进程因等待事件已发生而进入就绪队列。
等待进程也可由事件发生进唤醒。
由事件发生进程唤醒时,事件发生进程和被唤醒进程之间是合作关系。
因此,唤醒原语既可被系统进程调用,也可被事件发生进程调用。
我们称调用唤醒原语的进程为唤醒进程。
唤醒原语首先将被唤醒进程从相应的等待队列中摘下,将被唤醒进程置为就绪状态之后,送入就绪队列。
在把被唤醒进程送入就绪队列之后,唤醒原语既可以返回原调用程序,也可以转向进程调度,以便让调度程序有机会选择一个合适的进程执行。
图4左-阻塞原语右-唤醒原语
6,软件运行环境及限制
只能在配有JDK1.6以上、JBuilder、JCreator、JavaWorkShop、VisualAgeforJava等环境中运行。
8,测试数据
图5测试数据
8,结果输出及分析
(1)输入线程名,点击开始,如图:
图6输入线程名
(2)输出结果,分析,如图:
图7输出结果分析
(3)退出:
图8退出
9,心得体会
通过这次课程设计,我们更进一步的熟悉《计算机操作系统》的内涵,同时也对java语法和java语言的面向对象特性一定的理解,更加深和理解面向对象的基本概念和面向对象程序设计的基本原理;培养了我们对这些原理和设计原则进行面向对象的系统设计和开发;提高我们的编程能力,培养我们利用面向对象的开发方法进行系统开发的技巧和良好的程序设计风格;使我们进一步学习和利用软件工程思想进行软件开发和软件文档的编制。
操作系统是用户和计算机硬件之间的桥梁,用户通过软件向操作系统提交作业,每个作业有一个或多个进程组成。
所以本设计模拟实现计算机的主要功能,实现计算机的模拟进程调度与共享临界资源。
本模拟操作系统由三个系统进程组成,由原语管理所有的子进程和总的内存和资源分配,两个进程对临界区进行申请资源和占有。
而管理进程(原语)和子进程都是一个类的对象,不同的是系统进程由程序自动初始化和运行,而子进程须由模拟用户提交。
在这次编制中,我学会了很多东西,也找出了自己的一些不足。
通过这次我又加深了不少;其次是各个功能的算法,以前还是很模糊,现在总算有领悟啦;再次是整个工程的全局把握还不够,有时遗漏忘点,不过在队友的提醒和帮助下还是有所进步;最后也很高兴完成了设计。
10,参考文献
[1]汤子瀛哲凤屏汤小丹《计算机操作系统》(修订版)西安电子科技大学出版社2004
[2]威格尔斯沃恩《java程序设计高级教程》(第3版)清华大学出版社2005
[3]斯科特(美)《程序设计语言——实践之路》电子工业出版社2005
[4]胡伏湘雷军环等《Java程序设计使用教程》清华大学出版社2009
[5]朱战立《数据结构—java语言描述》清华大学出版社2005
[6]王晓东《计算机算法设计与分析》电子工业出版社2007
源程序代码:
publicclassMainFrameextendsJFrameimplementsFocusListener{
JTextAreajta=newJTextArea();
staticJTextFieldjtf[]=newJTextField[2];
staticJButtonjb[]=newJButton[2];
ThreadShowts=newThreadShow();
//界面设计
publicMainFrame(){
super("模拟多进程共享临界资源");
JLabeljl[]=newJLabel[2];
for(inti=0;ijtf[i]=newJTextField(12);
jtf[i].addFocusListener(this);
}
//设置按钮名称和位置
jl[0]=newJLabel("第一线程的名称:
");
jl[1]=newJLabel("第二线程的名称:
");
jb[0]=newJButton("模拟开始");
jb[1]=newJButton("模拟结束");
JMenuBarmb=newJMenuBar();
JMenujm1=newJMenu("文件(F)");
JMenujm2=newJMenu("编辑(E)");
JMenujm3=newJMenu("查看(V)");
JMenujm4=newJMenu("帮助(H)");
JMenuItemjmia1=newJMenuItem("打开(Ctrl+O)");
JMenuItemjmia2=newJMenuItem("保存(Ctrl+S)");
JMenuItemjmia3=newJMenuItem("打印(Ctrl+P)");
JMenuItemjmia4=newJMenuItem("退出(C)");
JMenuItemjmib1=newJMenuItem("撤消(Ctrl+Z)");
JMenuItemjmib2=newJMenuItem("全选(Ctrl+A)");
JMenuItemjmic1=newJMenuItem("工具栏(T)");
JMenuItemjmic2=newJMenuItem("状态栏(B)");
JMenuItemjmic3=newJMenuItem("刷新(R)");
JMenuItemjmid1=newJMenuItem("帮助主题(H)");
JMenuItemjmid2=newJMenuItem("关于软件(A)");
jmia4.addMouseListener(newMouseAdapter(){
publicvoidmousePressed(MouseEvente){
System.exit(0);
}
});
jmic3.addMouseListener(newMouseAdapter(){
publicvoidmousePressed(MouseEvente){
for(inti=0;ijtf[i].setText("");
}
}
});
jmid1.addMouseListener(newMouseAdapter(){
publicvoidmousePressed(MouseEvente){
JOptionPane.showMessageDialog(newJOptionPane(),"XXXXXXX","提示!
",JOptionPane.INFORMATION_MESSAGE);
}
});
jmid2.addMouseListener(newMouseAdapter(){
publicvoidmousePressed(MouseEvente){
JOptionPane.showMessageDialog(newJOptionPane(),"XXXXXXX","提示!
",JOptionPane.INFORMATION_MESSAGE);
}
});
Containercont=this.getContentPane();
cont.setLayout(newBorderLayout());
JPaneljp1=newJPanel();
JPaneljp2=newJPanel();
jp1.setLayout(newGridLayout(0,1));
jp1.add(mb);
mb.add(jm1);
mb.add(jm2);
mb.add(jm3);
mb.add(jm4);
jm1.add(jmia1);
jm1.add(jmia2);
jm1.add(jmia3);
jm1.addSeparator();
jm1.add(jmia4);
jm2.add(jmib1);
jm2.add(jmib2);
jm3.add(jmic1);
jm3.add(jmic2);
jm3.addSeparator();
jm3.add(jmic3);
jm4.add(jmid1);
jm4.addSeparator();
jm4.add(jmid2);
for(inti=0;iJPaneltemp=newJPanel();
temp.add(jl[i]);
temp.add(jtf[i]);
jp1.add(temp);
}
for(inti=0;ijp2.add(jb[i]);
jp1.add(jp2);
jp1.setBorder(newLineBorder(newColor(0,0,0),10));
jp1.setBorder(newLineBorder(newColor(238,238,238),10));
cont.setLayout(newBorderLayout());
cont.add(jp1,BorderLayout.NORTH);
jta.setEnabled(true);
JScrollPanejs=newJScrollPane(jta,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jta.setBorder(newLineBorder(newColor(34,57,12),1));
js.setBorder(newLineBorder(newColor(238,238,238),10));
cont.add(js,BorderLayout.CENTER);
this.setSize(335,435);//定义界面大小
this.setDefaultCloseOperation(3);
//设置当前界面显示时相对屏幕的位置
this.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width/2-175,
Toolkit.getDefaultToolkit().getScreenSize().height/2-200);
this.setResizable(false);
this.setVisible(true);
//jb1添加监听器
jb[1].addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEventarg0){
if(ts.tu1!
=null&&ts.tu1.isAlive())ts.tu1.interrupt();
if(ts.tu2!
=null&&ts.tu2.isAlive())ts.tu2.interrupt();
System.exit(0);
}
});
//jb0添加监听器
jb[0].addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEventarg0){
for(inti=0;iMainFrame.jb[0].setEnabled(false);
jta.setText("");
ts.run(jtf[0].getText().trim(),jtf[1].getText().trim(),jta);
}
});
}
publicstaticvoidmain(Stringares[]){
newMainFrame();
}
publicvoidfocusGained(FocusEventarg0){
//当用户点击文本框时,文本框就把当前内容清空
JTextFieldjtf=(JTextField)arg0.getSource();
jtf.setText("");
}
publicvoidfocusLost(FocusEventarg0){
}
}
//临界区
classThreadManagerimplementsRunnable{//指向要管理得临界资源
ThingSomeobj;
//记录obj是否已有使用者
booleanjud=false;
Vectorvec=newVector();
Stringname;
publicThreadManager(ThingSomets){
obj=ts;
}
publicvoidrun(){
while(vec.size()!
=0){
for(inti=0;iif(!
((Thread)vec.get(i)).isAlive()){
((Thread)vec.get(i)).interrupt();
vec.remove(i);
}
}
try{
Thread.currentThread().sleep(100);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
JOptionPane.showMessageDialog(null,"演示完毕","信息",//结束窗口
JOptionPane.INFORMAT