_进程管理实验报告

进程管理实验报告

一、进程与线程

1.实验目的:

1.通过本实验学习Linux中创建进程的方法。

2.学习系统调用fork的使用方法。

3.学习系统调用exec族调用的使用方法。

2.实验准备

1. 进程的创建

创建一个进程的系统调用很简单,只要调用fork函数就可以了。

   #include<unistd.h>

   pid_t fork();

   当一个进程调用了fork以后,系统会创建一个子进程,这个子进程和父进程是不同的地方只有它的进程ID和父进程ID,其他的都一样,就像父进程克隆(clone)自己一样,当然创建两个一模一样的进程是没有意义的,为了区分父进程和子进程,我们必须跟踪fork调用返回值。当fork调用失败的时候(内存不足或者是用户的最大进程数已到)fork返回—1,否则fork的返回值有重要的作用。对于父进程fork返回子进程ID,而对于fork子进程返回0,我们就是根据这个返回值来区分父子进程的。

2.关于fork的说明

   使用该函数时,该函数被调用一次,但返回两次,两次返回的区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程ID。

   将子进程ID返回给父进程的理由是:因为一个进程的子进程可以多于一个,所以没有一个函数可以是一个子进程获得其所有子进程的进程ID。

   而fork函数使子进程得到的返回值是0的理由是:一个子进程只会有一个父进程,所以子进程总是可以调用函数getpid获得其父进程的进程ID。

3.系统调用exec族调用的说明

   父进程创建子进程后,子进程一般要执行不同的程序。为了调用系统程序,我们可以使用系统调用exec族调用。Exec族调用有以下五个函数:

   int execl(const char *path,const char*arg,…);

   int execlp(const char *file, const char*arg,…);

   int execle(const char *path,const char*arg,…);

   int execv(const char *path,const char*argv[]);

   int execvp(const char *file, const char*argv[]);

   exec族调用可以执行给定程序。关于exec族调用的详细解说可以参考系统手册。

3.实验内容及步骤

编程实现使用fork函数创建子进程,以及在子进程中调用exec族调用的程序。

1、进入Linux操作系统中的终端显示如下:

在系统shell提示符下输入vi及文件名后,进就入vi编辑画面。如果系统内还不存在该文件,就意味着要穿件文件。如果系统内存在该文件,就意味着要编辑该文件。下面就是用vi编辑器创建文件的实例。

{root@localhost }#vi filename

此后文件的编译都使用同样的方法,不再赘述。

2、目前,Linux系统下的应用程序多由C语言编写,最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSIC标准的编译系统,能够编译用C、C++等语言编写的程序。

在使用GCC之前,下面的这个例子能够帮助用户迅速理解GCC的工作原理,并将其立即运用到实际的项目开发中去。

首先用vi编译器按照下面的内容创建一个名为hello.c的文件。

#filename:hello.c

#include

Int main(void)

{
      printf(“Hello World,Linux programming!”);

return 0;

}

         然后执行下面的命令编译和运行这段程序:

        #gcc hello.c –o hello

        #./hello

        Hello world,Linux programming!

       此后的程序均按照这种方法运行,下文中将不再赘述。

4.参考程序

1、使用fork函数创建子进程的程序 fork.c

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main(int argc,char *argv[]){

   pid_t childpid;

   if((childpid=fork())==0){

         printf("I am the child process,my ID is %ld\n",(long)getpid());

   }

   else if(childpid>0){

         printf("I am the parent process,my ID is %ld\n",(long)getpid());

   }

}

      2、创建子进程后调用系统调用execlp的程序 execlp.c

      #include <stdio.h>

#include <unistd.h>

int main(int argc,char * argv[])

{

          pid_t pid;

   pid=fork();

   if(pid<0){

         fprintf(stderr,"Fork Failed");

         exit(-1);

   }

   else if(pid==0){

         execlp("/bin/date","date",NULL);

   }//执行另外一个程序

   else{

         wait(NULL);

         printf("child complete\n");

         exit(0);

   }

}

5.实验结果

1.fork.c

2.execlp.c

 

第二篇:实验报告四

电子信息工程学系实验报告 ——适用于计算机课程

课程名称: 操作系统

实验项目名称:银行家算法 实验时间:2014.4.4-4.20

班级:计算机122 姓名:李鹏辉 学号:201210704214

实验报告四

实 验 目 的:

1.理解死锁避免相关内容;

2.掌握银行家算法主要流程;

3.掌握安全性检查流程。

操作系统中的死锁避免部分的理论进行实验。要求实验者设计一个程序,该程序可对每一次资源申请采用银行家算法进行分配。

实 验 环 境:

PC机、windows2000 操作系统、Turbo C 2.0 / VC++6.0

实 验 内 容 及 过 程:

设计一个有N个进程并行的进程调度程序。

进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。具体描述如下:

每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。

分析:进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。

进程的运行时间以时间片为单位进行计算。

每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。 就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。

如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后按照优先数的大小把它插入就绪队列等待CPU。

每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。 重复以上过程,直到所要进程都完成为止。

调度算法的参考流程图如下:

死锁避免定义:在系统运行过程中,对进程发出的每一个资源申请进行动态检查,并根据检查结果决定是否分配资源:若分配后系统可能发生死锁,则不予分配,否则予以分配。

由于在避免死锁的策略中,允许进程动态地申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,进程等待。其中最具有代表性的避免死锁算法是银行家算法。

1 系统安全状态

1)安全状态

所谓系统是安全的,是指系统中的所有进程能够按照某一种次序分配资源,并且依次地运行完毕,这种进程序列{ P1 ,P2 …Pn}就是安全序列。如果存在这样一个安全序列,则系统是安全的。

并非所有的不安全状态都会转为死锁状态,但当系统进入不安全状态后,便有可能进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态。所以避免死锁的实质:系统在进行资源分配时,如何使系统不进入不安全状态。

实验报告四

2)安全状态之例

假设系统有三个进程,共有12台磁带机。各进程的最大需求和T0时刻已分配情况如下表:

实验报告四

答:T0时刻是安全的,因为存在安全序列:P2 ?P1? P3

不安全序列:P1?…

P3?…

P2?P3?P1

3)由安全状态向不安全状态的转换

如果不按照安全序列分配资源,则系统可能会由安全状态进入不安全状态。例如,在T0时刻以后,P3又请求1台磁带机,若此时系统把剩余3台中的1台分配给P3,则系统便进入不安全状态。 因为,此时也无法再找到一个安全序列, 例如,把其余的2台分配给P2,这样,在P2完成后只能释放出4台,既不能满足P1尚需5台的要求,也不能满足P3尚需6台的要求,致使它们都无法推进到完成,彼此都在等待对方释放资源,即陷入僵局,结果导致死锁。

2 利用银行家算法避免死锁

1)银行家算法中的数据结构

① 可利用资源向量Available。

这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果Available[j]=K,则表示系统中现有Rj类资源K个。

② 最大需求矩阵Max。

最大需求矩阵Max。这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。

③ 分配矩阵Allocation

这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。

④ 需求矩阵Need

这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。

Need[i,j]=Max[i,j]-Allocation[i,j]

2)银行家算法

设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi

实验报告四

发出资源请求后,系统按下述步骤进行检查:

(1) 如果Requesti[j]≤Need[i,j],便转向步骤2;否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。

(2) 如果Requesti[j]≤Available[j],便转向步骤(3);否则, 表示尚无足够资源,Pi须等待。

(3) 系统试探着把资源分配给进程Pi

实验报告四

,并修改下面数据结构中的数值:

Available[j]∶=Available[j]-Requesti[j];

Allocation[i,j]∶=Allocation[i,j]+Requesti[j];

Need[i,j]∶=Need[i,j]-Requesti[j];

(4) 系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则, 将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。

行家算法的参考流程图如下:

实验报告四

实验报告四

3)安全性算法

实验报告四

实验报告四

实验报告四

(1) 设置两个向量: ① 工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work∶=Available;

② Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]∶=false; 当有足够资源分配给进程时, 再令Finish[i]∶=true。

(2) 从进程集合中找到一个能满足下述条件的进程:

① Finish[i]=false;

② Need[i,j]≤Work[j]; 若找到, 执行步骤(3), 否则,执行步骤(4)。 (3) 当进程Pi

实验报告四

获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

Work[j]∶=Work[i]+Allocation[i,j];

true; Finish[i]∶= go to step (2);

(4) 如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态。

安全性算法的参考流程图如下:

实 验 结 果 及 分 析:

实验报告四

实验报告四

创建基本信息

实验报告四

进程1申请资源成功

实验报告四

申请资源大于总资源,失败

实 验 心 得:

本次实验,我们看到银行家算法确实能保证系统时时刻刻都处于安全状态,但它要不断检测每个进程对各类资源的占用和申请情况,需花费较多的时间。

附 录:

#include "string.h"

#include "iostream.h"

#define M 5

#define N 3

#define FALSE 0

#define TRUE 1

int MAX[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};

int AVAILABLE[N]={10,5,7};

实验报告四

int ALLOCATION[M][N]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};

int NEED[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};

int Request[N]={0,0,0};

void main()

{

int i=0,j=0;

char flag='Y';

void showdata();

void changdata(int);

void rstordata(int);

int chkerr(int);

showdata();

while(flag=='Y'||flag=='y')

{

i=-1;

while(i<0||i>=M)

{

cout<<" 请输入需申请资源的进程号(从0到"<<M-1<<",否则重输入!):";

cin>>i;

if(i<0||i>=M) cout<<" 输入的进程号不存在,重新输入!"<<endl;

}

cout<<" 请输入进程"<<i<<"申请的资源数"<<endl;

for (j=0;j<N;j++)

{

cout<<" 资源"<<j<<": ";

cin>>Request[j];

if(Request[j]>NEED[i][j])

{

cout<<" 进程"<<i<<"申请的资源数大于进程"<<i<<"还需要"<<j<<"类资源的资源量!"; cout<<"申请不合理,出错!请重新选择!"<<endl<<endl;

flag='N';

break;

}

else

{

if(Request[j]>AVAILABLE[j])

{

cout<<" 进程"<<i<<"申请的资源数大于系统可用"<<j<<"类资源的资源量!"; cout<<"申请不合理,出错!请重新选择!"<<endl<<endl;

flag='N';

break;

}

}

}

if(flag=='Y'||flag=='y')

{

changdata(i);

if(chkerr(i))

{

rstordata(i);

showdata();

}

else

showdata();

}

else

showdata();

cout<<endl;

cout<<" 是否继续银行家算法演示,按'Y'或'y'键继续,按'N'或'n'键退出演示:"; cin>>flag;

}

}

void showdata()

{

int i,j;

cout<<" 系统可用的资源数为:"<<endl<<endl;

cout<<" ";

for(j=0;j<N;j++) cout<<" 资源"<<j<<": "<<AVAILABLE[j];

cout<<endl;

cout<<endl;

cout<<" 各进程还需要的资源量:"<<endl<<endl;

for(i=0;i<M;i++)

{

cout<<"进程"<<i<<":";

for(j=0;j<N;j++) cout<<" 资源"<<j<<", "<<NEED[i][j];

cout<<endl;

}

cout<<endl;

cout<<" 各进程已经得到的资源量:"<<endl<<endl;

for(i=0;i<M;i++)

{

cout<<"进程"<<i<<":";

for(j=0;j<N;j++) cout<<" 资源"<<j<<": "<<ALLOCATION[i][j];

cout<<endl;

}

cout<<endl;

};

void changdata(int k)

{

int j;

for(j=0;j<N;j++)

{

AVAILABLE[j]=AVAILABLE[j]-Request[j];

ALLOCATION[k][j]=ALLOCATION[k][j]+Request[j]; NEED[k][j]=NEED[k][j]-Request[j];

}

};

void rstordata(int k)

{

int j;

for(j=0;j<N;j++)

{

AVAILABLE[j]=AVAILABLE[j]+Request[j];

ALLOCATION[k][j]=ALLOCATION[k][j]-Request[j]; NEED[k][j]=NEED[k][j]+Request[j];

}

};

int chkerr(int s)

{

int WORK,FINISH[M],temp[M];

int i,j,k=0;

for(i=0;i<M;i++) FINISH[i]=FALSE;

for(j=0;j<N;j++)

{

WORK=AVAILABLE[j];

i=s;

while(i<M)

{

if(FINISH[i]==FALSE&&NEED[i][j]<=WORK) {

WORK=WORK+ALLOCATION[i][j];

FINISH[i]=TRUE;

temp[k]=i;

k++;

i=0;

}

else

{

i++;

}

}

for(i=0;i<M;i++)

if(FINISH[i]==FALSE)

{

cout<<endl;

cout<<" 系统不安全!!!本次资源申请不成功!!!"<<endl; cout<<endl;

return 1;

}

}

cout<<endl;

cout<<" 经安全性检查,系统安全,本次分配成功。"<<endl; cout<<endl;

cout<<" 本次安全序列:";

for(i=0;i<M;i++) cout<<"进程"<<temp[i]<<"->";

cout<<endl<<endl;

return 0;

};

备注:以上各项空白处若填写不够,可自行扩展

相关推荐