操作系统课程实验报告
姓名
学号
任课教师
指导教师
评阅教师
实验地点
丽泽楼C304-2      丽泽楼C304-1       (请勾选实际实验地点)
实验时间
实验课表现
出勤和个人表现Q1(15+15(组长评分)=30分)
得分:
实验
总分
(Q1+Q2+Q3+Q4)
实验完成情况Q2(45分(组长评分,教师根据实际情况微调))
得分:
实验编号与实验名称:
实验2 进程控制管理
实验目的:
1)掌握进程的概念,明确进程的含义
2)认识并了解并发执行的实质
实验内容及要求(详见实验讲义与实验指导书):
1)编写一段程序,使用系统调用fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。试观察记录屏幕上的显示结果,并分析原因。
2)修改上述程序,每一个进程循环显示一句话。子进程显示'daughter  ''son  ……',父进程显示 'parent  ……',观察结果,分析原因。
实验用到的软件(:
虚拟机VMWare/Virtual Box
fedora15
实验内容及关键步骤(代码)Q3(15分)
1. 按照上一次实验的步骤,进入后需要切换到管理员,输入“su root”,输入密码之后,可以输入“ls”查看目录下的文件。 附加:为了熟悉上一节实验课内容,我先创建了一个myleb2的文件夹,然后再在这个文件夹里创建一个子文件夹love,再在里面编译。
2. 开始编写代码,输入“vi test1.c”,按i开始编写,输入以下代码:
#include <stdio.h>
int main( )
{
int p1,p2;
while((p1=fork( ))= = -1);        /*创建子进程p1*/
if (p1= =0)  putchar('b');       
else
{
while((p2=fork( ))= = -1);  /*创建子进程p2*/
if(p2= =0)  putchar('c'); 
else  putchar('a');   
}
}
然后按ESC键后,输入“:wq”退出编译。
3. 退出后,输入“cat test1.c”可查看所输入的代码内容,输入“gcc test1.c”,然后输入“ls”查看,发现有a.out这个文件,然后运行它,输入“./a.out”,可看到输出的结果为“acb”。
4. 再创建一个编译,输入“vi test2.c”,输入以下代码:
#include <stdio.h>
main( )
{
int p1,p2,i;
while((p1=fork( ))= = -1);          /*创建子进程p1*/
if (p1= =0)
  for(i=0;i<10;i++)
printf("daughter  %d\n",i);
else
{
                while((p2=fork( ))= = -1);  /*创建子进程p2*/
if(p2= =0)
                  for(i=0;i<10;i++)
                      printf("son  %d\n",i);
else
                  for(i=0;i<10;i++)
                      printf("parent  %d\n",i);
}
}
5. 退出后,用同样方法查看此文件的代码内容。
6. 查看无问题后,输入“gcc –o test2 test2.c”,修改运行文件名,然后查看该文件夹下的所有文件,能看到“test2”运行文件。
7. 运行“test2”文件,输入“./test2”,可查看运行结果为“daughter 0  daughter 1daughter 2daughter 3….. daughter 9”。
8. 观察其他同学的输出结果,会发现有不一样的地方,例如:前一个程序运行结果有的是“bca”或者“bac”,后面这个结果也有许多不同之处。在思考和与同学讨论之后,分析这个结果的原因。
实验过程中遇到的问题解决办法与实验体会Q410分)
得分:
思考题:
1. 有一个系统调用可以用来创建进程:fork。这个系统调用会创建一个与调用进程相同的副本。调用后,父进程和子进程拥有相同的储存映像、同样的环境字符串和同样的打开文件。
系统调用格式:进程间通信实验报告心得 pid=fork( )fork(  )返回值意义如下:
0:在子进程中,pid变量保存的fork(  )返回值为0,表示当前进程是子进程。>0:在父进程中,pid变量保存的fork(  )返回值为子进程的id值(进程唯一标识符)。-1:创建失败。
如果fork( )调用成功,它向父进程返回子进程的PID,并向子进程返回0
fork()要完成这些操作:(1)为新进程分配一进程表项和进程标识符(2)检查同时运行的进程数目(3)拷贝进程表项中的数据(4)子进程继承父进程的所有文件(5)为子进程创建进程上、下文(6)子进程执行。
2. 因为如果fork( )调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork( )被调用了一次,但返回了两次。 所以,所建的新进程的入口就是是调用的fork( )父进程的副本。
3. 首先是读入文件内容,再次是看文件有没有指定程序运行,如果有则运行,如果没有则输出出错的信息。
实验中的问题及解决办法:
这次的实验主要是让我们从输出结果中分析问题。
1.首先是第一个程序,用c语言编写的代码,代码本身是没什么问题的,但奇怪的是输出结果却是三个都输出了。这是因为每个进程被创建后都有一个程序计数器,资源集一样,如:
while((p1=fork( ))= = -1);    /*创建子进程p1*/
while((p2=fork( ))= = -1);  /*创建子进程p2*/
对父进程而言,除了创建2个子进程之外,还要输出a,它和子进程的关系是竞争关系,同时需要使用CPU,当前获得什么进程,就输出什么进程。输出的结果为acb意为:先运行父进程,并输出,然后子进程被创建后,成为就绪队列,父进程可以运行,然后再开始创建子进程。
所以总的来说,就是从进程并发执行来看,各种情况都有可能。上面的三个进程没有同步措施,所以父进程与子进程的输出内容会叠加在一起。输出次序带有随机性。
2.然后是第二个程序,因为在有3个进程时,不同的电脑操作系统的调度算法是不一样的,因此也会有其他输出的次序,但3个程序都会输出。但是也有可能输出不了,而输出不了的,则说明它已经被挂起了。
比如这个程序,随着循环次数的不同,有例如“parent输出n次后,开始输出别的,再输出parent,即循环被无端的中断”的情况。也会有其他的情况。
所以总的来说,就是由于函数printf( )在输出字符串时不会被中断,因此,字符串内部字符顺序输出不变。但由于进程并发执行的调度顺序和父子进程抢占处理机问题,输出字符串的顺序和先后随着执行的不同而发生变化。
评阅教师特殊评语:
评阅教师:
日    期:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。