操作系统实验-第二讲、进程的创建
- 格式:doc
- 大小:529.50 KB
- 文档页数:10
进程的创建实验报告进程的创建实验报告引言:在计算机科学领域中,进程是一个非常重要的概念。
进程是计算机程序的执行实例,它具有独立的内存空间和执行环境。
进程的创建是操作系统中一个关键的操作,本实验旨在通过编写一个简单的程序来演示进程的创建过程。
实验目的:通过实验,我们的目标是深入理解进程的创建过程,并了解操作系统是如何管理进程的。
实验步骤:1. 引入必要的头文件:在开始编写代码之前,我们需要引入一些必要的头文件。
这些头文件包括<sys/types.h>、<sys/wait.h>和<unistd.h>。
这些头文件提供了创建进程所需的函数和数据类型。
2. 创建一个子进程:在主程序中,我们使用fork()函数来创建一个子进程。
fork()函数会在当前进程的基础上创建一个新的进程,这个新进程称为子进程。
子进程和父进程几乎完全相同,只有在返回值上有所区别。
如果fork()函数返回0,表示当前进程是子进程;如果返回一个正整数,表示当前进程是父进程。
3. 子进程的执行:在子进程中,我们可以编写任意的代码来执行特定的任务。
子进程可以使用exec()函数来执行其他程序,或者执行一系列的操作。
在本实验中,我们简单地输出一条信息,以展示子进程的执行过程。
4. 父进程的执行:在父进程中,我们可以编写代码来执行其他任务,或者等待子进程的结束。
在本实验中,我们使用wait()函数来等待子进程的结束。
wait()函数会暂停父进程的执行,直到子进程结束为止。
5. 编译和运行程序:在完成代码编写后,我们需要将程序编译成可执行文件,并运行它。
我们可以使用gcc编译器来编译程序,然后运行生成的可执行文件。
实验结果:在运行程序后,我们可以观察到以下结果:子进程开始执行。
父进程等待子进程结束。
子进程结束。
父进程继续执行。
结论:通过本实验,我们成功地演示了进程的创建过程。
我们了解了操作系统是如何管理进程,并且掌握了使用fork()函数来创建子进程的方法。
操作系统实验二实验报告一、实验目的本次操作系统实验二的主要目的是深入理解和掌握进程管理的相关概念和技术,包括进程的创建、执行、同步和通信。
通过实际编程和实验操作,提高对操作系统原理的认识,培养解决实际问题的能力。
二、实验环境本次实验使用的操作系统为 Windows 10,编程环境为 Visual Studio 2019。
三、实验内容及步骤(一)进程创建实验1、首先,创建一个新的 C++项目。
2、在项目中,使用 Windows API 函数`CreateProcess`来创建一个新的进程。
3、为新进程指定可执行文件的路径、命令行参数、进程属性等。
4、编写代码来等待新进程的结束,并获取其退出代码。
(二)进程同步实验1、设计一个生产者消费者问题的模型。
2、使用信号量来实现生产者和消费者进程之间的同步。
3、生产者进程不断生成数据并放入共享缓冲区,当缓冲区已满时等待。
4、消费者进程从共享缓冲区中取出数据进行处理,当缓冲区为空时等待。
(三)进程通信实验1、选择使用管道来实现进程之间的通信。
2、创建一个匿名管道,父进程和子进程分别读写管道的两端。
3、父进程向管道写入数据,子进程从管道读取数据并进行处理。
四、实验结果及分析(一)进程创建实验结果成功创建了新的进程,并能够获取到其退出代码。
通过观察进程的创建和执行过程,加深了对进程概念的理解。
(二)进程同步实验结果通过使用信号量,生产者和消费者进程能够正确地进行同步,避免了缓冲区的溢出和数据的丢失。
分析结果表明,信号量机制有效地解决了进程之间的资源竞争和协调问题。
(三)进程通信实验结果通过管道实现了父进程和子进程之间的数据通信。
数据能够准确地在进程之间传递,验证了管道通信的有效性。
五、遇到的问题及解决方法(一)在进程创建实验中,遇到了参数设置不正确导致进程创建失败的问题。
通过仔细查阅文档和调试,最终正确设置了参数,成功创建了进程。
(二)在进程同步实验中,出现了信号量使用不当导致死锁的情况。
实验二进程创建实验学时:3实验类型:(验证)一、实验目的1. 理解进程概念以及进程和程序的区别;2. 理解进程并发执行的实质;3. 掌握解决进程同步问题的基本方法;4. 培养学生分析和设计程序的能力。
二、实验条件Linux平台。
三、实验原理及相关知识1.实验相关知识点进程的基本概念;进程控制;进程同步;经典进程的同步问题。
2.系统调用系统调用是一种进入系统空间的办法。
通常,在OS的核心中都设置了一组用于实现各种系统功能的子程序,并将它们提供给程序员使用。
程序员在需要OS提供某种服务的时候,便可以调用一条系统调用命令,去实现希望的功能,这就是系统调用。
因此,系统调用就像一个黑箱子一样,对用户屏蔽了操作系统的具体动作而只是提供了调用功能的接口。
不同的操作系统有各自的系统调用方法。
如windows API,便是windows的系统调用。
Linux 的系统调用与之不同的是源于Linux内核代码完全公开,所以可以细致的分析出其系统调用的机制。
3.系统调用和普通函数的区别(1)运行于不同的系统状态用户程序可以通过系统调用进入系统空间,在核心态执行;而普通函数则只能在用户空间当中运行。
(2)通过软中断切换由于用户程序使用系统调用后要进入系统空间,所以需要调用一个软中断;而普通函数在被调用时则没有这个过程。
4.系统调用的类型系统调用的作用与它属在的操作系统有密切关系。
根据操作系统的性质不同,它们所提供的系统调用会有一定的差异,不过对于普通操作系统而言,应该具有下面几类系统调用:(1)进程控制类型;(2)文件操纵类型;(3)进程通信类型;(4)信息维护类型。
5.系统调用的实现机制由于操作系统的不同,其系统调用的实现方式可能不一样,然而实现机制应该是大致相同的,一般包含下面几个步骤:(1)设置系统调用号,在系统当中,往往设置多条系统调用命令,并赋予每条系统调用命令一个唯一的系统调用号。
根据分配系统调用号方式的不同分为:直接方式和参数表方式。
第1篇一、实验背景与目的在操作系统中,进程是执行程序的基本单位。
进程的建立是操作系统管理进程的第一步,也是理解进程生命周期的基础。
本实验旨在通过实践操作,让学生了解进程的创建过程,掌握创建进程的方法,并理解进程间的关系。
二、实验环境- 操作系统:Linux- 编程语言:C语言- 工具:gcc编译器、gdb调试器三、实验内容1. 理解进程创建的基本概念- 进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。
- 进程的五个基本状态:创建态、就绪态、运行态、阻塞态、终止态。
2. 创建进程- 使用`fork()`系统调用创建进程。
- `fork()`系统调用:用于创建一个新的进程,即子进程。
子进程是父进程的一个副本,具有相同的内存空间和执行代码。
- 父进程和子进程的关系:父进程通过`fork()`系统调用返回值区分子进程和父进程。
如果返回值为0,则表示当前进程是子进程;如果返回值大于0,则表示当前进程是父进程,返回值是子进程的进程标识符。
3. 进程间通信- 使用管道(pipe)实现进程间通信。
- 管道是一种特殊的文件,用于实现进程间的数据传递。
4. 进程同步- 使用互斥锁(mutex)和条件变量(condition variable)实现进程同步。
- 互斥锁:用于保证在同一时刻只有一个进程可以访问共享资源。
- 条件变量:用于实现进程间的条件等待和通知。
四、实验步骤1. 编写C语言程序,使用`fork()`系统调用创建子进程。
2. 在父进程中,使用管道(pipe)创建一个管道,用于与子进程进行通信。
3. 在父进程中,通过管道向子进程发送数据。
4. 在子进程中,从管道接收数据,并处理数据。
5. 使用互斥锁和条件变量实现进程同步。
五、实验结果与分析1. 父进程和子进程成功创建。
2. 数据通过管道成功传递。
3. 进程间同步成功实现。
六、实验总结通过本次实验,我们了解了进程的创建过程,掌握了创建进程的方法,并理解了进程间的关系。
实验二进程的创建与控制姓名:梁斌学号:20121060186专业:计算机科学与技术(国防)一、实验目的1.加深对进程概念的理解,认识并发执行的本质。
2.分析进程竞争资源的现象,学习解决互斥的方法。
二、实验主要内容及设计1.使用fork( )创建两个子进程。
2.使用lockf( )给进程加锁。
三、实验内容及完成结果编写一段程序,使用系统调用fork( )创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符;父进程显示字符“a”,子进程分别显示字符“b”和“c”。
试观察记录屏幕上的显示结果,并分析原因。
〈程序〉# include<stdio.h>main(){int p1,p2;while((p1=fork())= = -1);/*创建子进程p1*/ if(p1= =0) /*子进程创建成功*/putchar(…b‟);else{while((p2= fork())= = -1);/*创建另一个子进程*/if(p2= =0)/*子进程创建成功*/putchar(…c‟);else putchar(…a‟);/*父进程执行*/}}<运行结果>四、结果及分析1.给出fork ( )的流程图fork( )流程图2.对进程创建中的程序进行分析为了进一步了解和进程如何创建,以及子进程和父进程的调用顺序和执行的代码,对上述程序做了如下修改# include<stdio.h>main(){int p1,p2;while((p1=fork())= = -1);printf(“p1=%d\n”,p1); /*p1为任意整数,调用父进程;p1为0,调用子进程*/if(p1= =0)printf(“b\n”);else{while((p2= fork())= = -1);printf(“p2=%d\n”,p2);/* p2为任意整数,调用父进程;p2为0,调用子进程*/if(p2= =0)printf(“c\n”);else printf(“a\n”);;}}执行结果分析:1.父进程和子进程的代码段都是上面的所有代码,不过子进程的代码只从创建此子进程那里开始执行2.程序在创建子进程的时候返回两个值:一个任意正整数(子进程的ID),返回给父进程;一个0,返回给子进程3.执行结果是bca,也就是系统在创建玩b,c两个子进程后,先调用执行b进程,输出‟b‟,接着调用执行c进程,输出‟c‟,最后执行父进程,输出‟a‟4.之所以有其他不同的字母输出顺序,是因为三个进程抢占cpu不同,从而导致三个进程被cpu调用执行的顺序不同,从而有不同的输出。
进程的创建一、实验目的1、掌握进程的概念,明确进程的含义2、认识并了解并发执行的实质。
二、实验内容1、编写一段程序,使用系统调用fork( )创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。
试观察记录屏幕上的显示结果,并分析原因。
2、修改上述程序,每一个进程循环显示一句话。
子进程显示'daughter …'及'son ……',父进程显示'parent ……',观察结果,分析原因。
三、实验结果及结果分析实验代码:1、#include <stdio.h>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');}}2、#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);elsefor(i=0;i<10;i++)printf("parent %d\n",i);}}运行结果:1、bca,bac, abc ,……2、parent…son…daughter..daughter..或parent…son…parent…daughter…等四、实验体会除strace 外,也可用ltrace -f -i -S ./executable-file-name查看以上程序执行过程。
一、实验目的1. 理解进程的概念及其在操作系统中扮演的角色。
2. 掌握在特定编程环境中创建进程的方法。
3. 分析进程创建的过程和机制。
4. 熟悉进程间通信和同步的基本原理。
二、实验环境1. 操作系统:Windows 102. 编程语言:C/C++3. 开发工具:Visual Studio 2019三、实验原理进程是操作系统中执行的基本单元,是系统进行资源分配和调度的基本单位。
在操作系统中,进程的创建是系统调用的过程,通过系统调用,父进程可以创建子进程。
在创建子进程时,子进程将继承父进程的某些属性,如环境变量、打开的文件等。
四、实验步骤1. 创建父进程- 编写一个简单的C/C++程序,使用`fork()`系统调用创建子进程。
2. 创建子进程- 在父进程中,通过`fork()`函数创建子进程。
`fork()`函数返回值有以下几种情况:- 返回0:表示子进程;- 返回子进程的进程ID:表示父进程;- 返回-1:表示创建子进程失败。
3. 父进程和子进程的区分- 通过检查`fork()`的返回值,父进程和子进程可以相互区分。
父进程可以通过返回值获取子进程的进程ID。
4. 父进程和子进程的通信- 使用管道(pipe)实现父进程和子进程之间的通信。
创建管道后,父进程通过管道向子进程发送数据,子进程从管道中读取数据。
5. 父进程和子进程的同步- 使用互斥锁(mutex)和条件变量(condition variable)实现父进程和子进程的同步。
父进程在完成工作后,可以通知子进程继续执行。
五、实验代码```c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#include <fcntl.h>int main() {int pipe_fd[2];pid_t pid;// 创建管道if (pipe(pipe_fd) == -1) {perror("pipe");exit(EXIT_FAILURE);}// 创建子进程pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (pid == 0) {// 子进程close(pipe_fd[1]); // 关闭管道的写端dup2(pipe_fd[0], STDIN_FILENO); // 将管道的读端复制到标准输入execlp("date", "date", NULL); // 执行date命令} else {// 父进程close(pipe_fd[0]); // 关闭管道的读端write(pipe_fd[1], "Hello, world!\n", 15); // 向管道写入数据close(pipe_fd[1]); // 关闭管道的写端wait(NULL); // 等待子进程结束printf("Child process exited with PID %d\n", pid);}return 0;}```六、实验结果与分析1. 父进程和子进程分别运行`date`命令和输出“Hello, world!”字符串。
进程创建实验报告第一篇:进程创建实验报告实验二进程的创建一、实验目的熟悉进程的创建过程,了解系统调用函数fork()和 execl()。
二、实验内容1、阅读实例代码fork1,并编辑、编译、运行,记录程序的运行结果,尝试给出合理的解释,查阅有关资料,掌握系统调用fork()的用法,返回值的意义。
2、阅读实例代码fork2,并编辑、编译、运行,记录程序的运行结果,尝试给出合理的解释,查阅有关资料,掌握在程序中运行一个操作系统命令和运行一个程序的方法。
3、修改fork2,使之能把运行的命令和程序作为参数传给fork2。
三、设计思想1、程序框架pid =-1 pid = 0 pid > 02、用到的文件系统调用函数 fork()和 execl()四、调试过程1、测试数据设计(1)fork1 命名程序1:编写程序1:编译程序1:运行程序1:(2)fork2 编写程序2:运行程序2:(3)修改fork2 编写修改程序2:修改后的运行结果:2、测试结果分析(1)对于程序1:因为系统调用fork()函数是一次调用两次返回值,而且先生成子进程还是父进程是不确定的,所以第一次执行生成子进程的时候返回的pid = 0,判断pid!=-1,所以输出了I’m the child.I’m the parent.第二次,执行父进程的时候,返回的是子进程的进程号pid > 0,即pid的值仍然不为-1,所以又输出了一次I’m the child.I’m the parent。
(2)对于程序2:第一次调用fork()函数时,由于执行的是子进程还是父进程是随机的,所以第一次对父进程返回的是子进程的进程号(大于0),即pid > 0,所以输出I’m the parent.Program end.当第二次执行子进程时返回值是0,即pid = 0,所以输出I’m the child.并调用了execl()函数,查看了指定路径中的文件。
操作系统实验报告哈尔滨工程大学计算机科学与技术学院第三讲进程的创建一、实验概述1. 实验名称进程的创建2. 实验目的1)、练习使用 EOS API 函数 CreateProcess 创建一个进程,掌握创建进程的方法,理解进程和程序的区别。
2)、调试跟踪 CreateProcess 函数的执行过程,了解进程的创建过程,理解进程是资源分配的单位。
3. 实验类型(验证、设计)验证型4. 实验内容1)、准备实验2)、练习使用控制台命令创建 EOS 应用程序的进程3)、练习通过编程的方式让应用程序创建另一个应用程序的进程4)、调试 CreateProcess 函数5)、调试 PsCreateProcess 函数6)、练习通过编程的方式创建应用程序的多个进程二、实验环境进行实验使用的操作系统、编译器、语言及工具等。
操作系统:Windows XP编译器: Tevalaton OS Lab语言: C++三、实验过程(每次实验不一定下面6条都写,根据实际情况定)*需要解决的问题以及解答(1)、程序创建2个进程创建的情况下,实验指导P133-4的*NewProcess和6的*ProcessObject变化情况,监控变量界面截图。
答:在PsCreateProcess函数中找到调用PspCreateProcessEnvironment函数的代码行(create.c文件的163行),并在此行添加一个断点。
按 F5继续调试,到此断点处中断。
按F11调试进入 PspCreateProcessEnvironment 函数。
在调用ObCreateObject函数的代码行(create.c文件的第418行)添加一个断点。
按F5继续调试,到此断点处中断。
按F10执行此函数后中断。
将表达式*NewProcess添加到“监视”窗口中,继续一步步调试可以观察到进程控制块的成员变量的值的变化,如下图:接下来调试初始化进程控制块中各个成员变量的过程:当从 PspCreateProcessEnvironment 函数返回到 PsCreateProcess 函数后,停止按 F10。
此时“监视”窗口中已经不能再显示表达式*NewProcess 的值了,在PsCreateProcess 函数中是使用ProcessObject 指针指向进程控制块的,所以将表达式*ProcessObject 添加到“监视”窗口中就可以继续观察新建进程控制块中的信息。
接下来继续使用F10一步步调试 PsCreateProcess 函数中的代码,同样要注意进程控制块中的成员变量的变化:(2)、尝试根据之前PsCreateProcess 函数和PspCreateProcessEnvironment 函数执行过程的跟踪调试,绘制一幅进程创建过程的流程图。
答:(3)、思考与练习,在源代码文件NewTwoProc.c 提供的源代码基础上进行修改,要求使用hello.exe 同时创建10个进程。
要给出源代码及解释和运行界面截图。
答:1). 设计思路创建10个进程时,可以使用 PROCESS_INFORMATION 类型定义一个有 10 个元素的数组,每一个元素对应一个进程。
使用一个循环创建 10个子进程,然后再使用一个循环等待 10 个子进程结束,得到退出码后关闭句柄。
2). 算法实现在创建10个进程的程序中,为了保证只有在10个进程都创建成功的情况下才执行后续操作,引入一个变量flag,只有10个程序都创建成功时flag=1,出现创建失败的情况时flag=0,当flag=1时再执行后续操作。
否则直接关闭已创建的进程并退出系统。
附实现代码:#include "EOSApp.h"STARTUPINFO StartupInfo;PROCESS_INFORMATION my_process[10];ULONG ulExitCode; //子进程退出码INT nResult=0; //main函数返回值。
0表示成功,非0表示失败。
#ifdef _DEBUG__asm("int $3\n nop");#endifprintf("Create ten processes and wait for the processes exit...\n\n");//使子进程和父进程使用相同的标准句柄。
StartupInfo.StdInput=GetStdHandle(STD_INPUT_HANDLE);StartupInfo.StdOutput=GetStdHandle(STD_OUTPUT_HANDLE);StartupInfo.StdError=GetStdHandle(STD_ERROR_HANDLE);int i;int flag = 1;int cnt = 0;for(i=0; i<10; i++) {//Create ten processes at the same timeif(CreateProcess("A:\\Hello.exe", NULL, 0, &StartupInfo, &my_process[i])) //if ok jumpcnt++;else {//else output errorprintf("CreateProcess Failed,Error code:0x%X.\n", GetLastError());nResult = 1;flag = 0;break;//if flag == 0 there must be some error}}if(flag == 1){//创建子进程成功,等待子进程运行结束。
for(i=0; i<10; i++) {WaitForSingleObject(my_process[i].ProcessHandle, INFINITE);}//得到并输出子进程的退出码。
for(i=0; i<10; i++){GetExitCodeProcess(my_process[i].ProcessHandle,&ulExitCode);printf("\nThe process%d exit with%d.\n", i+1, ulExitCode);}//关闭不再使用的句柄。
for(i=0; i<10; i++) {CloseHandle(my_process[i].ProcessHandle);CloseHandle(my_process[i].ThreadHandle);}} else {for( ; cnt>0; cnt--) {GetExitCodeProcess(my_process[cnt].ProcessHandle,&ulExitCode);printf("\nThe process%d exit with%d.\n", i+1, ulExitCode);CloseHandle(my_process[cnt].ProcessHandle);CloseHandle(my_process[cnt].ThreadHandle);}}return nResult;}(4)、学习本书第 5 章中的 5.2 节,了解关于线程的相关知识,然后尝试调试 PspCreateThread 函数,观察线程控制块(TCB)初始化的过程。
(5)、在 PsCreateProcess 函数中调用了 PspCreateProcessEnvironment 函数后又先后调用了PspLoadProcessImage 和 PspCreateThread 函数,学习这些函数的主要功能。
能够交换这些函数被调用的顺序吗?思考其中的原因。
答:PspCreateProcessEnvironment创建了地址空间和分配了句柄表。
PspLoadProcessImag是将进程的可执行映像加载到了进程的地址空间中。
PspCreateThread创建了进程的主线程。
这三个函数知道自己要从哪里开始执行,执行哪些指令。
因此不能交换他们的顺序。
*程序运行时的初值以及运行结果:3.1 准备实验建立一个EOS Kernel 项目和 EOS 应用程序项目。
3.2 练习使用控制台命令创建 EOS 应用程序的进程将本实验文件夹中的Hello.exe文件拖动到FloppyImageEditor工具窗口的文件列表中释放,Hello.exe文件即被添加到软盘镜像文件中,按F5启动调试,在EOS的控制台中输入命令“A:\Hello.exe”后回车,结果如下图:3.3 练习通过编程的方式让应用程序创建另一个应用程序的进程使用 NewProc.c 文件中的源代码替换之前创建的 EOS 应用程序项目中的 EOSApp.c 文件内的源代码,F5 启动调试,激活虚拟机窗口查看应用程序输出的内容:3.4 调试 CreateProcess 函数F5 启动调试 EOS 应用程序,在 main 函数中调用 CreateProcess 函数的代码行(第 57 行)添加一个断点。
按 F5 继续调试,在断点处中断。
按F11 调试进入 CreateProcess 函数。
在“调试”菜单的“窗口”中选择“反汇编”,会在“反汇编”窗口中显示 CreateProcess 函数的指令对应的反汇编代码。
“反汇编”窗口的左侧显示的是指令所在的虚拟地址。
可以看到所有指令的虚拟地址都大于 0x80000000,说明内核( kernel.dll)处于高 2G 的虚拟地址空间中,如图:设置 main 函数的调用堆栈帧为活动的。
在“反汇编”窗口中查看 main 函数的指令所在的虚拟地址都是小于0x80000000,说明应用程序(eosapp.exe)处于低2G 的虚拟地址空间中,如图:3.5 调试 PsCreateProcess 函数已在需要解决的问题以及解答中给出过程3.6 练习通过编程的方式创建应用程序的多个进程用 NewTwoProc.c 文件中的源代码替换 EOS 应用程序项目中 EOSApp.c 文件内的源代码,生成后启动调试,查看多个进程并发执行的结果。
四、实验体会本次实验主要练习使用EOS API函数 CreateProcess创建一个进程,掌握创建进程的方法,理解进程和程序的区别。
以及调试跟踪 CreateProcess函数的执行过程,了解进程的创建过程,理解进程是资源分配的单位。
通过本次实验了解了了解操作系统中进程与线程的区别。
通过对进程以及线程进行不同的创建方式,观察启动之后的区别,从而理解操作系统启动后的工作方式。