操作系统课程设计
设计文档
一、选题
根据本人编程的经验以及对操作系统的了解,决定选取题目一以完成本作业。
(附:题目一的内容)
实现UP、DOWN原语
产生3个进程:
两个进程模拟需要进入临界区的用户进程。
当需要进入临界区时,显示:“进程x请求进入临界区…”,同时向管理进程提出申请;
申请返回,表示进入了临界区。在临界区中等待一段随机时间,并显示:“进程x正在临界区…”;
当时间结束,显示:“进程x退出临界区…”,同时向管理进程提出退出申请;
当申请返回,显示:“进程x已退出临界区。”
一个进程作为原语的管理进程,接受其他进程的临界区进入请求:
如果允许进入,则根据DOWN 原语的操作步骤设置相应变量,然后返回;
如果不允许进入,则进入循环等待,直到允许为止;
退出时模拟UP 操作。
进程间通信可以采用信号、消息传递、管道或网络通信方式。
二、文档
2.1 选题相关原理
题目要求建立三个进程,模拟进入临界区,然后用一个进程进行管理。在我们的操作系统,通过信号量进行访问是很常见的保证进程同步的方法。在我们的实验中,我决定用DELPIHI来模拟实现这一过程,具体思路如下:
DELPHI程序运行后,主进程(在DELPHI中只有一个进程,但我们可以把线程看作进程)就是我们看到的应用程序,这个程序应该理解是一个原语的管理进程,它可能管理我们的临界区,注意是管理,例如我决定用一个数来模拟临界区,如果该数大于0,那么临界区可用;如果该数小于0,那么临界区不可用;这个数的改变只能由主线程来做到,而其它的线程如果要申请临界区或退出临界区只能通过对主线程进行申请。
因此这样设计是符合题目要求的。
主要考虑建立以下函数,或功能及数据设计:(由于时间关系,就不画流程图了,但应该很容易理解)
1、 主进程部分
功能部分:
(1) 根据线程的请求分配临界区:如果符合条件(临界区可被申请,而且还有临界区还有资源),那么将该资源分配给申请线程,同时显示一下分配情况;如果不符合条件,那么要求线程等待资源;调功能(3)显示状态信息
(2) 根据线程的请求释放临界区:如果正在临界区的线程请求退出,则实现DOWN操作,把信号量置位,把资源置位;调功能(3)显示状态信息
(3) 显示GUI状态:如当前的状态,临界区资源的个数等等
数据部分:
(1) 要创建线程的名称列表,因此就可以创各种线程(绝对不止两个都可以)
(2) 模拟临界区资源的一个内存变量,模拟是否使用临界区的另一个内存变量(这是因为事实上的控件都不支持线程内读写)
2、 子线程部分
功能部分:
(1) 申请资源:向主线程申请资源,如果成功,进入资源并利用,如果不成功,循环等待并SLEEP,如果10秒后仍没有资源可利用,线程自动停止(以免死锁)并报错误信息
(2) 模拟使用:申请得资源后,随机使用一段时间
(3) 申请释放;释放资源要向主进程提供申请,如果成功,那么停止,如果不成功,循环等待并SLEEP,如果10秒后仍没有得到主线程的答复,报错误信息并终止;
数据部分:
(1) 线程的名称,由线程创建时由主线程指定;
(2) 是否申请到资源标志
(3) 是否终止标志(因此主线程就可以控制是否将线程终止)
(4) 休眠时间:如果申请不到资源或不能申请退出等待的时间
(5) 显示的信息列表:显示的信息有“不能申请资源”、“不能退出资源”两种情况(暂这样考虑)
根据我们的这个设计,应该是能很好的模拟出题目要求的。
2.2 设计时有关的数据和代码实现
数据和代码实现在这里不详述了,其实就是对上面那部分的实现。主要参考书《DELPHI 6 开发人员指南》;
简单的介绍如下所示(请注意区分功能,因为这里不全的,详细信息请参看源代码部分)
2.3 最终结果
最终结果,是一模拟程序。程序运行状态如下50
操作系统多进程设计
三、原代码
采用Delphi 6.0集成工具开发,语言object pascal,开发环境P4 1.8G+384 DDR +Windows 2000运行并测试成功;
unit uMain;
interface
需要完整内容的请联系QQ3710167,本文免费,转发请注明源于www.lwfree.cn
type
TMain = class(TForm)
GroupBox1: TGroupBox;
lbox: TListBox;
Panel1: TPanel;
StatusBar1: TStatusBar;
GroupBox2: TGroupBox;
btnstartMonitor: TBitBtn;
btnStopMonitor: TBitBtn;
GroupBox3: TGroupBox;
GroupBox4: TGroupBox;
Label3: TLabel;
Label4: TLabel;
btnCreate: TBitBtn;
edtName: TEdit;
Label5: TLabel;
Label6: TLabel;
edtRetry: TSpinEdit;
GroupBox5: TGroupBox;
Label8: TLabel;
edtSource: TEdit;
edtUse: TEdit;
Label9: TLabel;
lvInfo: TListView;
Splitter1: TSplitter;
edtWaitTime: TSpinEdit;
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Label7: TLabel;
edtTimes: TSpinEdit;
Label10: TLabel;
CheckBox1: TCheckBox;
Label11: TLabel;
procedure btnstartMonitorClick(Sender: TObject);
procedure btnStopMonitorClick(Sender: TObject);
procedure btnCreateClick(Sender: TObject);
private
{ Private declarations }
public
isMonitor: boolean; //is monitor the status ,is false didn't display the statu information
procedure AddInfoTolvinfo(index: integer; s: string);
function GetInfoFromlvInfo(index: integer): string;
procedure AddInfo(s: string);
{ Public declarations }
end;
TDemoProcedure = class(TThread)
public
ListIndex: integer;
constructor Create();
private
{ Private declarations }
protected
procedure Execute; override;
procedure WantSource;
procedure Wantsourceok;
procedure donWantSource;
procedure donWantsourceOK;
procedure EndThisRun;
procedure ShowError;
procedure ShowErrorEx; //释放资源被锁定,强制释放以防死锁
end;
const
sRun = '运行状态';
sWait = '申请资源';
sWaitOk = '申请资源成功,进行使用期';
sExit = '申请释放资源';
sExitOk = '释放资源ok';
var
Main: TMain;
implementation
{$R *.dfm}
procedure TMain.btnstartMonitorClick(Sender: TObject);
begin
isMonitor := true;
btnStartMonitor.Enabled := false;
btnStopMonitor.Enabled := true;
end;
procedure TMain.btnStopMonitorClick(Sender: TObject);
begin
isMonitor := false;
btnStartMonitor.Enabled := true;
btnStopMonitor.Enabled := false;
end;
procedure TMain.btnCreateClick(Sender: TObject);
var
strName: string;
waitTime, Retry, Times: integer;
p: TListitem;
isMore: boolean; //判断该进程是否已存在
i: integer;
DemoProcedure: TDemoProcedure;
begin
strName := Trim(edtName.Text);
waitTime := edtWaitTime.Value;
Retry := edtRetry.Value;
Times := edtTimes.Value;
if Trim(edtName.Text) = '' then
begin ShowMessage('模拟进程的名称必须输入,随便输'); edtName.SetFocus; exit; end;
if ((WaitTime <= 0) or (Retry <= 0)) then
begin ShowMessage('时间是不能设为小于等于0的数的,随便输'); exit; end;
if (Times <= 0) then
begin ShowMessage('重试次数不能少于0'); edtTimes.SetFocus; exit; end;
isMore := false;
for i := 0 to lvinfo.Items.Count - 1 do
begin
if lvinfo.Items[i].Caption = strName then
begin isMore := true; break; end;
end;
if isMore then
begin ShowMessage('模拟进程的名称要唯一哦'); edtName.SetFocus; exit; end;
with lvinfo do //如果成功,写入进程信息列表中
begin
p := Items.Add;
p.Caption := strname;
p.SubItems.Add(intTostr(waitTime));
p.SubItems.Add(intTostr(Retry));
p.SubItems.Add(sRun);
end;
DemoProcedure.WaitTime := waitTime * 1000;
DemoProcedure.RetryTime := Retry * 1000;
DemoProcedure.Resume;
end;
procedure TMain.AddInfotoLvinfo(index: integer; s: string);
begin
if lvinfo.Items.Count - 1 < index then exit;
if index < 0 then exit;
lvinfo.Items[index].SubItems[2] := s; ;
end;
function TMain.GetInfoFromlvInfo(index: integer): string;
begin
result := lvinfo.Items[index].SubItems[2];
end;
procedure TMain.AddInfo(s: string);
begin
if not isMonitor then exit;
lbox.Items.Add(s);
// Application.ProcessMessages;
end;
{ TDemoProcedure }
constructor TDemoProcedure.Create;
操作系统多进程设计
begin
FreeOnTerminate := True;
inherited Create(True);
end;
procedure TDemoProcedure.donWantSource;
begin
with Main do
begin
isDonotWantSource := not CheckBox1.checked;
if isDonotWantSource then
begin
//释放资源
edtuse.Text := '否';
Edit1.Text := '无';
edtSource.Text := intTostr(strToint(edtSource.Text) + 1);
AddinfoTolvinfo(ListIndex, '释放资源成功');
Addinfo(format('%s 试图释放资源---资源尚未锁定,释放成功', [strname]));
end
else
begin
需要完整内容的请联系QQ3710167,本文免费,转发请注明源于www.lwfree.cn
end;
end;
end;
procedure TDemoProcedure.donWantsourceOK;
begin
with Main do
begin
AddinfoTolvinfo(ListIndex, '释放资源');
Addinfo(format('%s 成功释放资源---释放资源后马上会自动终止本进程', [strname]));
end;
end;
procedure TDemoProcedure.EndThisRun;
begin
with Main do
begin
addinfoTolvinfo(listindex, '成功结束');
addinfo(format('%s 成功结束', [strName]));
end;
end;
procedure TDemoProcedure.Execute;
var
i: integer;
begin
i := 0;
repeat
synchronize(WantSource);
if isWantSource then break
else
sleep(RetryTime);
Inc(i);
until (i >= Times);
if i >= Times then
begin //未申请到资源退出
synchronize(self.ShowError);
self.Terminate;
end;
//进行运行态
synchronize(wantsourceOK);
//运行
sleep(waittime); //模拟
//运行完毕申请释放资源
i := 0;
repeat
synchronize(donWantSource);
if isDonotWantSource then break
else
sleep(RetryTime);
Inc(i);
until (i >= Times);
if i >= Times then
synchronize(self.ShowErrorEx);
self.Terminate;
end;
synchronize(donWantSourceOk);
synchronize(EndThisRun);
// self.Terminate;
end;
procedure TDemoProcedure.ShowError;
begin
with Main do
begin
addinfoTolvinfo(ListIndex, '超时错误并停止');
addinfo(format('%s 经过%d秒重试,仍然没有成功,超时并终止线程', [strName, RetryTime]));
end;
end;
procedure TDemoProcedure.ShowErrorEx;
begin
with Main do
begin
addinfoTolvinfo(ListIndex, '超时错误并停止');
addinfo(format('%s 经过%d秒重试,用户仍然锁定不准释放资源,为了防止死锁,强制释放并终止线程', [strName, RetryTime]));
edtuse.Text := '否';
Edit1.Text := '无';
edtSource.Text := intTostr(strToint(edtSource.Text) + 1);
end;
end;
procedure TDemoProcedure.WantSource;
begin
with Main do
begin
if edtuse.Text = '是' then
self.isWantSource := false
else
self.isWantSource := True;
if isWantSource then
begin
//申请资源
edtuse.Text := '是';
Edit1.Text := strname;
edtSource.Text := intTostr(strToint(edtSource.Text) - 1);
AddinfoTolvinfo(ListIndex, '申请资源成功');
Addinfo(format('%s 试图申请资源---资源尚未使用,申请成功', [strname]));
end
else
需要完整内容的请联系QQ3710167,本文免费,转发请注明源于www.lwfree.cn
end;
end;
end;
procedure TDemoProcedure.Wantsourceok;
begin
with Main do
begin
AddinfoTolvinfo(ListIndex, '使用资源状态');
Addinfo(format('%s 成功申请资源---正在使用过程中,将运行%d毫秒', [strname, waittime]));
end;
end;
end.