进程管理实验报告
进程调度实验报告分析

信息工程学院实验报告课程名称:操作系统Array实验项目名称:进程调度一、实验目的:用高级语言编写和调试一个有 N个进程并发的进程调度程序,以加深对进程的概念及进程调度算法的理解。
二、实验设备与器件PC机、windows2000 操作系统、VC++6.0三、实验内容与步骤设计一个有N个进程并发的进程调度程序。
进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。
具体描述如下:每个进程有一个进程控制块( PCB)表示。
进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。
分析:进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。
进程的到达时间为进程输入的时间。
进程的运行时间以时间片为单位进行计算。
每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
就绪进程获得 CPU后都只能运行一个时间片。
用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后按照优先数的大小把它插入就绪队列等待CPU。
每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止。
调度算法的参考流程图如下:实验步骤1.编写一个有N个进程并发的进程调度程序。
2.在上机环境中输入程序,调试,编译。
3.设计输入数据,写出程序的执行结果。
4.根据具体实验要求,填写好实验报告。
四、实验结果及分析1、两个进程并发执行进程执行:进程轮转直至全部进程都执行完。
五、实验总结(实验过程中遇到的问题及解决的方法,做为本实验的心得体会)通过老师老师的帮助,进行试验,我深刻理解操作了,对调度的原理基本把握。
31301378_钱晨_实验三

浙江大学城市学院实验报告课程名称操作系统原理实验实验项目名称实验三进程的创建和简单控制学生姓名钱晨专业班级软件1302 学号31301378实验成绩指导老师(签名)日期注意:●务请保存好各自的源代码,已备后用。
●完成本实验后,将实验报告上传ftp。
如没有个人文件夹,请按学号_姓名格式建立。
ftp://hujupload:123456@10.66.28.222:2007/upload●文件名为:学号_姓名_实验XX,如30801001_XXXX_实验01一. 实验目的和要求1.掌握进程的概念和进程的状态,对进程有感性的认识;2.掌握进程创建方法;3.认识进程的并发执行,了解进程族之间各种标识及其存在的关系;4.熟悉进程的创建、阻塞、唤醒、撤销等控制方法。
二、实验内容1.了解有关Linux进程的属性和进程的层次结构;2.学习有关Linux的前台和后台进程;3.学习有关Linux命令的顺序执行和并发执行;4.学习有关挂起和终止进程;5.了解并发程序的不可确定性,进行简单并发程序设计。
三、实验步骤(一)Shell下的进程控制1、用ps查看进程。
查看ps命令的帮助文件,尝试不同的参数,并观察结果,记录截图。
2、kill命令使用。
截图说明。
3、pstree命令使用。
截图说明。
(二)Linux简单进程编程每个步骤请运行程序、截图,并解释运行结果,回答实验指导书的问题。
1i、并发进程之间的切换ii2个子进程分别执行一次,然后P1子进程执行一次,接着父进程执行,代表P1进程结束。
P2子进程执行,父进程再执行,代表P2结束。
2、iP1进程先执行,然后P2进程执行,最后父进程执行ii由于函数printf( )在输出字符串时不会被中断,因此,字符串内部字符顺序输出不变iii3、iii Fork每次被重新调用iii 运行一个进程超过计算机的一个时钟周期,被切换ivV后者进程ID不改变4、iii sleep(1)延长进程执行的时间iiiwait() 让父进程等待子进程结束才执行5、#include<unistd.h>#include<stdio.h>#include<sys/types.h>#include<stdlib.h>main(){int p1;int i;while((p1=fork())==-1);if(p1==0){printf("i am the child process,my process id is %d\n",getpid());for(i=0;i<4;i++){sleep(3);system("/bin/ps");}}else{wait();printf("i am the parent process, my process id is %d\n",getpid());}}四、讨论、心得记录实验感受、上机过程中遇到的困难及解决办法、遗留的问题、意见和建议等。
操作系统实验报告

篇一:操作系统实验报告完全版《计算机操作系统》实验报告班级:姓名:学号:实验一进程控制与描述一、实验目的通过对windows 2000编程,进一步熟悉操作系统的基本概念,较好地理解windows 2000的结构。
通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解windows 2000中进程的“一生”。
二、实验环境硬件环境:计算机一台,局域网环境;软件环境:windows 2000 professional、visual c++6.0企业版。
三、实验内容和步骤第一部分:程序1-1windows 2000 的gui 应用程序windows 2000 professional下的gui应用程序,使用visual c++编译器创建一个gui应用程序,代码中包括了winmain()方法,该方法gui类型的应用程序的标准入口点。
:: messagebox( null, “hello, windows 2000” , “greetings”,mb_ok) ;/* hinstance */ , /* hprevinstance */, /* lpcmdline */, /* ncmdshow */ )return(0) ; }在程序1-1的gui应用程序中,首先需要windows.h头文件,以便获得传送给winmain() 和messagebox() api函数的数据类型定义。
接着的pragma指令指示编译器/连接器找到user32.lib库文件并将其与产生的exe文件连接起来。
这样就可以运行简单的命令行命令cl msgbox.cpp来创建这一应用程序,如果没有pragma指令,则messagebox() api函数就成为未定义的了。
这一指令是visual studio c++ 编译器特有的。
接下来是winmain() 方法。
其中有四个由实际的低级入口点传递来的参数。
操作系统lab2实验报告

操作系统lab2实验报告实验目的:本实验的目的是通过设计和实现一个简单的操作系统内核,加深对操作系统基本概念和原理的理解。
具体实验内容包括进程管理、内存管理和文件系统的设计与实现。
实验环境:1.操作系统:Linux2.编程语言:C语言一、实验背景1.1 操作系统简介操作系统是计算机系统中的一个重要组成部分,负责管理和控制计算机的各种资源,提供用户和应用程序的接口,以及协调和调度各种任务的执行。
1.2 实验目标本实验的主要目标是设计和实现一个简单的操作系统内核,包括进程管理、内存管理和文件系统等功能。
二、实验内容2.1 进程管理①进程创建描述进程创建的过程和相关数据结构,包括创建新进程的系统调用、进程控制块等。
②进程调度描述进程调度的算法和实现方式,包括进程调度队列、调度算法等。
③进程同步与通信描述进程同步和通信的机制和方法,包括信号量、互斥锁、条件变量等。
2.2 内存管理①内存分配描述内存分配的算法和实现方式,包括连续内存分配、非连续内存分配等。
②页面置换描述页面置换的算法和实现方式,包括最优页面置换算法、先进先出页面置换算法等。
2.3 文件系统①文件操作描述文件操作的系统调用和相关数据结构,包括文件打开、读写、关闭等。
②文件系统结构描述文件系统的组织结构和实现方式,包括超级块、索引节点、块位图等。
三、实验步骤3.1 环境搭建搭建实验环境,包括安装Linux操作系统、编译器等。
3.2 进程管理实现根据设计要求,实现进程创建、调度、同步与通信等功能。
3.3 内存管理实现根据设计要求,实现内存分配、页面置换等功能。
3.4 文件系统实现根据设计要求,实现文件操作和文件系统结构。
3.5 测试与调试编写测试用例,对实现的操作系统内核进行测试和调试,并记录实验结果。
四、实验结果分析分析测试结果,评估实验过程中遇到的问题和解决方法,总结操作系统内核的性能和功能特点。
五、实验总结对实验过程中的收获和经验进行总结,提出改进和优化的建议。
查看程序的进程和线程实验报告

查看程序的进程和线程实验报告篇一:程序实验2:11-多线程编程---实验报告程序实验二:11-多线程编程实验专业班级实验日期 5.21 姓名学号实验一(p284:11-thread.c)1、软件功能描述创建3个线程,让3个线程重用同一个执行函数,每个线程都有5次循环,可以看成5个小任务,每次循环之间会有随即等待时间(1-10s)意义在于模拟每个任务到达的时间是随机的没有任何的特定规律。
2、程序流程设计3.部分程序代码注释(关键函数或代码)#include#include#include#define T_NUMBER 3#define P_NUMBER 5#define TIME 10.0void *thrd_func(void *arg ){(本文来自: 小草范文网:查看程序的进程和线程实验报告) int thrd_num=(int)arg;int delay_time =0;int count =0;printf("Thread %d is staraing\n",thrd_num);for(count=0;count {delay_time =(int)(rand()*TIME/(RAND_MAX))+1;sleep(delay_time);printf("\tTH%d:job%d delay =%d\n",thrd_num,count,delay_time);}printf("%d finished\n",thrd_num);pthread_exit(NULL);}int main(){pthread_t thread[T_NUMBER];int no=0,res;void * thrd_ret;srand(time(NULL));for(no=0;no {res=pthread_create(&thread[no],NULL, thrd_func,(void*)no);if(res!=0){printf("Creay th %d faild\n",no);exit(res);}}printf("success\nwaiting\n");for(no=0;no {res=pthread_join(thread[no],&thrd_ret);if(!res){printf("t %d joined\n",no);}else{printf("T %djoined faild\n",no);}}return 0;}4.编译、运行方法及结果(抓屏)5.结果分析由运行结果可以看出,创建线程、释放资源按照顺序,而每个线程的运行和结束是独立与并行的。
实验一 进程的控制

实验一进程的控制一、实验目的:熟悉vi全屏幕编辑器及gcc编译器的使用和可执行文件的执行;熟悉进程的创建、撤销、执行和父进程的同步。
以加深对进程概念和并发执行的理解,明确进程与程序之间的区别。
二、实验内容:1、了解系统调用fork()、exec()、exit()和wait()等功能和实现过程;2、使用vi编辑器输入一个C语言程序,用gcc编译器编译,然后运行可执行文件a.out;3、编写一段C程序,使用系统调用fork()创建两个子进程。
当此程序执行时,在系统中有一个父进程和两个子进程活动,让每一个进程在屏幕上显示一个字符;父进程显示字符“a”,子进程分别显示字符“b”、“c”。
试观察记录屏幕上的显示结果,并分析原因。
4、编一段程序,实现父进程创建子进程,每个进程都在屏幕上显示自己的ID号。
观察记录ID显示的顺序并分析原因。
实验二、进程间通信一、实验目的:通过进程的创建、执行、终止,实现父、子进程间的同步。
二、实验内容及要求:1、编写一程序,父进程创建一个子进程,父进程等待子进程,子进程执行完后自我终止,并唤醒父进程,父、子进程执行时打印有关信息。
2、编写一个C程序使其能完成:父进程创建一个子进程,在子进程运行时显示当前目录下的所有文件和目录,父进程输出子进程和自己进程的ID。
在程序运行时控制进程的顺序;子进程先执行,父进程后执行。
实验三:进程间管道通信一、实验目的及要求:学习利用管道机制实现进程间的通信,加深对管道通信机制的理解。
二、实验内容1、了解系统调用pipe()、read()、write()、lockf()等功能及实现过程。
2、编写一段程序,利用无名管道(用pipe()创建)实现进程间的通信。
父进程创建两个子进程,两个子进程分别向管道中写一条消息:“I am child1.”和“I am child2.”而父进程从管道中读出这两条消息,并显示在屏幕上。
实验四:文件管理一、实验目的及要求:熟悉文件的操作。
进程调度算法的实现实验报告记录
进程调度算法的实现实验报告记录————————————————————————————————作者:————————————————————————————————日期:南昌大学实验报告---(4)进程调度算法的实现学生姓名:学号:专业班级:实验类型:□验证□综合■设计□创新实验日期:实验成绩:一、实验目的通过实验加强对进程调度算法的理解和掌握。
二、实验内容编写程序实现进程调度算法,具体可以编写程序实现先来先服务算法或优先度高者调度算法。
三、实验要求1、需写出设计说明;2、设计实现代码及说明;3、运行结果;四、主要实验步骤1、分析实验内容,画出算法流程图;2、根据流程图写出实验代码;3、编译代码,验证结果正确与否;4、对程序进行修改,得到最后结果。
流程图如下:开始系统随机产生数据将数据按照到达时间从小到大排序用户输入数据进程到达时前一个进程是否已经完成完成时间=服务时间+前一个进程完成时间完成时间=服务时间+到达时间周转时间=完成时间-到达时间带权周转时间=完成时间/服务时间是否所有进程已完成计算输出结果结束YN YN YN五、实验数据及处理结果六、实验体会或对改进实验的建议在做这个实验的时候,一开始以为很简单,只要做简单的加减乘除就行了,但是仔细做过以后发现需要考虑很多情况。
比如说输入进程到达时间的时候,要是乱序的该怎么办?还有到达时间和服务时间等等定义的都是整型变量,但是带权周转时间确会得到小数,此时就需要用到强制转换。
在做系统产生随机数的时候也要考虑随机数的范围,如到达时间可以为0,但是服务时间却不能为0,否则带权周转时间的计算会出错。
七、参考资料《计算机操作系统》《计算机操作系统实验指导书》《C程序设计》《C语言程序设计_现代方法》八、实验代码#include <stdio.h>#include <stdlib.h>#include <time.h>#define N 5 //进程个数,可改变int rt[N]; //到达时间int st[N]; //服务时间int ct[N]; //完成时间int cyt[N]; //周转时间float rct[N]; //带权周转时间float av[2];int n,m,c=1,which;void line() //美化程序,使程序运行时更加明朗美观{printf("------------------------------------------------------------------\n");}void start() //表示FCFS算法开始{line();printf(" FCFS算法开始\n");printf(" ——Designed by Zhang Hong\n"); line();}void end() //表示FCFS算法结束{line();printf(" FCFS算法结束,谢谢使用\n");line();}void input(){printf("请输入%d个进程的到达时间:",N);for (n=0;n<N;n++)scanf("%d",&rt[n]);printf("请输入%d个进程对应的服务时间:",N);for (n=0;n<N;n++)scanf("%d",&st[n]);}void random(){srand((unsigned)time(NULL));for (n=0;n<N;n++){rt[n]=rand()%100;for (m=0;m<n;m++)if (n!=0 && rt[n]==rt[m]){rt[n]=rand()%100;m=0;}st[n]=rand()%98+1;for (m=0;m<n;m++)if (n!=0 && st[n]==st[m]){st[n]=rand()%98+1;m=0;}}}void ordination() //重新排序,应对出现输入的到达时间为乱序的情况{int temp;for (n=0;n<N;n++)for (m=0;m<N-n-1;m++)if (rt[m+1]<rt[m]){temp=rt[m+1];rt[m+1]=rt[m];rt[m]=temp;temp=st[m+1];st[m+1]=st[m];st[m]=temp;}}void fcfs() //执行fcfs算法{av[0]=0;av[1]=0;ct[0]=rt[0]+st[0];for (n=1;n<N;n++){if (ct[n-1]>=rt[n]) //考虑当前一个进程完成而后一个进程还没有到达的情况ct[n]=ct[n-1]+st[n];elsect[n]=rt[n]+st[n];}for (n=0;n<N;n++)cyt[n]=ct[n]-rt[n];for (n=0;n<N;n++)rct[n]=(float)cyt[n]/(float)st[n];for (n=0;n<N;n++){av[0]+=(float)cyt[n]/N;av[1]+=rct[n]/N;}}void output() //输出结果{line();printf("进程名\t");for (n=0;n<N;n++)printf("\t%c",65+n);printf("\t平均\n到达时间");for (n=0;n<N;n++)printf("\t%d",rt[n]);printf("\n服务时间");for (n=0;n<N;n++)printf("\t%d",st[n]);printf("\n完成时间");for (n=0;n<N;n++)printf("\t%d",ct[n]);printf("\n周转时间");for (n=0;n<N;n++)printf("\t%d",cyt[n]);printf("\t%0.1f",av[0]);printf("\n带权周转时间");for (n=0;n<N;n++)printf("\t%0.1f",rct[n]);printf("\t%0.1f",av[1]);printf("\n");line();}void main(){start();for (;c==1;){for (;;){printf("输入数据还是由系统随机产生数据?\n1、输入数据\t2、系统随机产生数据\n请输入:");scanf("%d",&which);if (which==1){input();break;}elseif (which==2){random();break;}printf("输入错误,请重新输入!");}ordination(); //进程按照到达时间进行排序fcfs();output();printf("继续输入,退出输入。
linux常用命令实验实验报告 -回复
linux常用命令实验实验报告-回复Linux常用命令实验实验报告一、引言在计算机领域,掌握常用命令是非常重要的。
对于使用Linux操作系统的用户来说,熟悉常用命令更是必备的技能之一。
本篇实验报告将以"Linux常用命令"为主题,介绍并实验一些常用的Linux命令,包括文件与目录管理、权限管理、网络管理、进程管理等方面的命令。
通过本次实验,希望进一步巩固和提升大家对Linux操作系统的理解和实践能力。
二、实验一:文件与目录管理1. 文件列表命令:ls首先,我们来介绍一下`ls`命令,该命令用于列出当前目录下的所有文件和文件夹。
通过在终端中输入`ls`命令,可以查看当前目录下的文件列表。
2. 创建目录命令:mkdir接下来,我们将尝试使用`mkdir`命令创建一个新的目录。
可以输入`mkdir directory_name`来创建一个名为"directory_name"的目录。
3. 切换目录命令:cd使用`cd`命令可以切换当前工作目录。
例如,要进入某个目录,可以使用`cd directory_name`命令。
要返回上一级目录,可以使用`cd ..`。
4. 复制文件命令:cp`cp`命令用于复制文件和目录。
要复制一个文件,可以使用`cp source_file destination_file`命令。
例如,`cp file1.txt file2.txt`将会复制"file1.txt"并将其命名为"file2.txt"。
5. 删除文件命令:rm要删除一个文件,可以使用`rm file_name`命令。
例如,要删除"file.txt"文件,可以输入`rm file.txt`。
6. 查找文件命令:find使用`find`命令可以在文件系统中查找文件。
例如,`find / -namefile_name`将会在根目录下找到名为"file_name"的文件。
进程调度算法实验报告
操作系统实验报告(二)实验题目:进程调度算法实验环境:C++实验目的:编程模拟实现几种常见的进程调度算法,通过对几组进程分别使用不同的调度算法,计算进程的平均周转时间和平均带权周转时间,比较各种算法的性能优劣。
实验内容:编程实现如下算法:1.先来先服务算法;2.短进程优先算法;3.时间片轮转调度算法。
设计分析:程序流程图:1.先来先服务算法2.短进程优先算法3.时间片轮转调度算法实验代码:1.先来先服务算法#include <iostream.h>#define n 20typedef struct{int id; //进程名int atime; //进程到达时间int runtime; //进程运行时间}fcs;void main(){int amount,i,j,diao,huan;fcs f[n];cout<<"请输入进程个数:"<<endl;cin>>amount;for(i=0;i<amount;i++){cout<<"请输入进程名,进程到达时间,进程运行时间:"<<endl; cin>>f[i].id;cin>>f[i].atime;cin>>f[i].runtime;}for(i=0;i<amount;i++) //按进程到达时间的先后排序{ //如果两个进程同时到达,按在屏幕先输入的先运行for(j=0;j<amount-i-1;j++){ if(f[j].atime>f[j+1].atime){diao=f[j].atime;f[j].atime=f[j+1].atime;f[j+1].atime=diao;huan=f[j].id;f[j].id=f[j+1].id;f[j+1].id=huan;}}}for(i=0;i<amount;i++){cout<<"进程:"<<f[i].id<<"从"<<f[i].atime<<"开始"<<","<<"在"<<f[i].atime+f[i].runtime<<"之前结束。
计算机操作系统实训教程之进程的创建实验报告
计算机操作系统实训教程实验报告姓名王学杰专业计算机应用技术班级班课程操作系统实验项目进程的创建【实验目的】.加深对进程、进程树等概念的理解。
.进一步明确进程和程序的区别。
.理解进程并发执行的实质。
.掌握系统中进程的创建方法及并发执行的情况。
【实验内容】.编写一段程序,使用系统调用()创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一段字符信息。
.学习对后台执行程序的控制方式。
.分析程序执行过程中产生的子进程情况。
【实验步骤】一、、编写源代码生成源文件“$ ”。
.编译“$ –”。
.前台运行“$ ”(按组合键终止死循环的程序)。
.多次使用–命令查看进程状态。
.使用命令控制该进程。
二、编写源代码生成源文件“”。
.编译源文件生成可执行程序“”:“$ –”。
.后台运行“$ ”。
.查看进程树“$ ”。
三例编写源代码生成源文件“”。
.编译源文件生成可执行程序“”:“$ –”。
.运行“$ ”。
四编写源代码生成源文件“”。
.编译源文件生成可执行程序“”:“$ –”。
.运行“$”。
五编写源代码生成源文件“”。
.编译源文件生成可执行程序“”:“$ –”。
运行结果如下【实验总结】一、入门知识一个进程,包括代码、数据和分配给进程的资源。
()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。
然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。
相当于克隆了一个自己。
调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:)在父进程中,返回新创建子进程的进程;)在子进程中,返回;)如果出现错误,返回一个负值;二、()与()区别()与()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别:. ():子进程拷贝父进程的数据段,堆栈段():子进程与父进程共享数据段. ()父子进程的执行次序不确定保证子进程先运行,在调用或之前与父进程数据是共享的,在它调用或之后父进程才可能被调度运行。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
北方工业大学 《计算机操作系统》实验报告 实验名称 进程管理 实验序号 1
实验日期 2013.11.20 实验人 一、实验目的和要求 1.加深对进程概念的理解,明确进程和程序的区别 2.进一步认识并发执行的实质 3.分析进程争用资源的现象,学习解决进程互斥的方法 4.了解Linux系统中进程通信的基本原理
二、相关背景知识 1.Linux编译运行程序 格式 gcc [option] [sourcefilename] 最简单的是:gcc hello.c 默认的情况下将生成a.out的可执行性文件,你只需要在终端上输入./a.out就可以看到执行的结果。如果想指定生成目标文件的名字那么你可以加上 -o选项,命令如下: gcc -o hello hello.c
2. 保存文件至U盘 插入U盘,保证其与主机连接良好。在Linux终端界面执行如下命令: mount –t auto /dev/sda1 /mnt/usb 注意: 1) /mnt/usb目录必须已经存在,如果不存在可以新建这个目录。 2) U盘在系统关闭后再拔出。
三、实验内容 1.进程的创建 编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。试观察记录屏幕上的显示结果,并分析原因。 2.进程的控制 修改已有程序,将每个进程输出一个字符改为每个进程输出几行字符,再观察程序执行时屏幕上的现象,并分析原因。如果在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。 3.进程的软中断通信 北方工业大学 2014-5-13 第2页/共9页 使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按Del键);当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止: Child process 1 is killed by parent! Child process 2 is killed by parent! 父进程等待两个子进程终止后,输出如下的信息后终止: Parent process is killed! 4.进程的管道通信 编制一段程序,实现进程的管道通信。使用系统调用pipe()建立一条管道线;两个子进程P1和P2分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message! 而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求父进程先接收P1发来的消息,然后再接收P2发来的消息。
四、关键数据结构与函数的说明 fork()函数:fork函数用于创建一个新进程(子进程),返回整数。正确返回:等于0,创建子进程;大于0,从父进程返回的子进程的ID值。错误返回:等于-1,即进程创建失败。
exit()函数:exit()函数是进程结束最常调用的函数。在正常终止时,exit()函数返回进程结束状态。
signal(): signal()函数是允许调用进程控制软中断信号的处理。 kill()函数:kill()函数用于结束执行中的程序或者任务。 pipe()函数:pipe函数用于创建一个管道 wait()函数:wait()函数常用来控制父进程与子进程的同步。在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()函数返回继续执行原程序。
五、编译与执行过程截图 1. 北方工业大学
2014-5-13 第3页/共9页 2. (1) 进程无锁
(2) 进程加锁 北方工业大学
2014-5-13 第4页/共9页 3.
4.
六、实验结果与分析 1.运行结果:abc。 分析:进程并发执行,输出的结果可能是abc的排列组合。fork()创建进程所需的时间要多于输出一个字符的时间,因此在主程序创建进程2的同时,进程1输出“b”,进程1、进程2和主程序的执行次序及输出次序是随机的。 2.(1)进程无锁 运行结果:输出的各进程的字符串相互交错。 分析:由于进程的执行具有并发性这个特征,因此会产生字符交叉的情况,即某一个进程在自己的时间片当中使用处理机,但是当时间片结束,还没有完成,但也必须由下一个进程接管处理机,因为它就进入了阻塞的状态。多个进程反复出现,所以就出现了输出的字符交叉的情况。
(2)进程加锁 运行结果:先输出完父进程再输出第二个子进程的所有字符串,最后输出第一个子进程。 分析:对进程加锁后,就表明只能由该程序占用处理机,必须这些完这段程序才能执行下一段,因为不会出现交叉的情况。 3.运行结果:输入 “Ctrl+c”后显示:Child process 1 is killed by parent!
Child process 2 is killed by parent! 北方工业大学 2014-5-13 第5页/共9页 分析:程序到waiting()函数时,因为wait_mark!=0一直在循环,处于等待状态;当signal()捕捉键盘上来的中断信号时,调用stop(),让wait_mark=0,于是程序能跳出waiting(),执行下面的程序,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后分别输出。 4.运行结果:Child 1 is sending a message! Child 2 is sending a message!
分析:当写进程完成任务,把要求的数据写入管道后,便会睡眠等待。直到读进程将管道中的数据读取取出后,再把写进程唤醒。当读进程试图从一空管道中读取数据时,也应睡眠等待,直至写进程将数据写入管道后,才将其唤醒。当一个进程正对pipe进行读/写操作时,另一进程必须等待,程序中使用lock(fd[1],1,0)函数实现对管道的加锁操作,用lock(fd[1],0,0)解除管道的锁定,所以在进程1使用完管道并解锁后进程2才能使用。
七、调试时遇到的问题及解决方法(提供BUG截屏)
八、调试后的程序源代码 1. #include main() { int p1,p2; while((p1=fork())==-1); if(p1==0) putchar('b'); else { while((p2=fork())==-1); if(p2==0) putchar('c'); else putchar('a'); } } 北方工业大学 2014-5-13 第6页/共9页 2. (1)进程无锁 #include main() { int p1,p2,i; while((p1=fork())==-1); if(p1==0) for(i=0;i<10;i++) printf("first son\n"); else { while((p2=fork())==-1); if(p2==0) for(i=0;i<10;i++) printf("second son\n"); else for(i=0;i<10;i++) printf("farther\n"); } }
(2)进程加锁 #include #include main() { int p1,p2,i; while((p1=fork())==-1); if(p1==0) { lockf(1,1,0); for(i=0;i<10;i++) printf("first son\n"); lockf(1,0,0); } else { while((p2=fork())==-1); if(p2==0) { lockf(1,1,0); for(i=0;i<10;i++) printf("second son\n"); lockf(1,0,0); } else { lockf(1,1,0); for(i=0;i<10;i++) printf("farther\n"); lockf(1,0,0); } } } 北方工业大学 2014-5-13 第7页/共9页 3. #include #include #include #include void waiting(),stop(); int wait_mark;
void main() { int p1,p2; while ((p1=fork())==-1); if(p1>0) { while ((p2=fork())==-1); if (p2>0) { wait_mark=1; signal(SIGINT,stop); waiting(); kill(p1,16); kill(p2,17); wait(0); wait(0); printf("parent process is killed \n"); exit(0); } else { wait_mark=1; signal(17,stop); signal(SIGINT,stop); waiting( ); lockf(1,1,0); printf("child 2 process is killed \n"); lockf(1,0,0); exit(0); } } else { wait_mark=1; signal(16,stop); signal(SIGINT,stop); waiting( ); lockf(1,1,0); printf("child 1 process is killed \n"); lockf(1,0,0); exit(0); } } void waiting() { while (wait_mark!=0);