操作系统课程实验报告
姓名 | 学号 | 系 | |||||||||
任课教师 | 指导教师 | 评阅教师 | |||||||||
实验地点 | 丽泽楼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 1,daughter 2,daughter 3….. daughter 9”。 8. 观察其他同学的输出结果,会发现有不一样的地方,例如:前一个程序运行结果有的是“bca”或者“bac”,后面这个结果也有许多不同之处。在思考和与同学讨论之后,分析这个结果的原因。 | |||||||||||
实验过程中遇到的问题解决办法与实验体会Q4(10分) | 得分: | ||||||||||
思考题: 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小时内删除。
发表评论