实验2.2进程的控制
- 格式:doc
- 大小:363.00 KB
- 文档页数:4
操作系统实验二进程管理以下是为大家整理的操作系统实验二进程管理的相关范文,本文关键词为操作系统,实验,进程,管理,,您可以从右上方搜索框检索更多相关文章,如果您觉得有用,请继续关注我们并推荐给您的好友,您可以在综合文库中查看更多范文。
操作系统实验实验二进程管理学号姓名班级华侨大学电子工程系实验目的1、理解进程的概念,明确进程和程序的区别。
2、理解并发执行的实质。
3、掌握进程的创建、睡眠、撤销等进程控制方法。
实验内容与要求基本要求:用c语言编写程序,模拟实现创建新的进程;查看运行进程;换出某个进程;杀死进程等功能。
实验报告内容1、进程、进程控制块等的基本原理。
进程是现代操作系统中的一个最基本也是最重要的概念,掌握这个概念对于理解操作系统实质,分析、设计操作系统都有其非常重要的意义。
为了强调进程的并发性和动态性,可以给进程作如下定义:进程是可并发执行的程序在一个数据集合上的运行过程,是系统进行资源分配和调度的一个独立单位。
进程又就绪、执行、阻塞三种基本状态,三者的变迁图如下:就绪I/o完成时间片完进程调度I/o请求阻塞执行由于多个程序并发执行,各程序需要轮流使用cpu,当某程序不在cpu上运行时,必须保留其被中断的程序的现场,包括:断点地址、程序状态字、通用寄存器的内容、堆栈内容、程序当前状态、程序的大小、运行时间等信息,以便程序再次获得cpu时,能够正确执行。
为了保存这些内容,需要建立—个专用数据结构,我们称这个数据结构为进程控制块pcb(processcontrolblock)。
进程控制块是进程存在的惟一标志,它跟踪程序执行的情况,表明了进程在当前时刻的状态以及与其它进程和资源的关系。
当创建一个进程时,实际上就是为其建立一个进程控制块。
在通常的操作系统中,pcb应包含如下一些信息:①进程标识信息。
为了标识系统中的各个进程,每个进程必须有惟一的标识名或标识数。
②位置信息。
指出进程的程序和数据部分在内存或外存中的物理位置。
实验二进程管理(二)进程的控制实验一、实验目的1、掌握进程另外的创建方法2、熟悉进程的睡眠、同步、撤消等进程控制方法二、实验内容1、用fork( )创建一个进程,再调用exec( )用新的程序替换该子进程的内容2、利用wait( )来控制进程执行顺序三、实验过程进入LINUX系统。
打开虚拟机,在vi中编写程序,在终端输入文件名,执行指令,得出运行结果。
1.运行程序:2.运行实验结果:四、回答问题(1)可执行文件加载时进行了哪些处理?可执行文件加载时首先是创建一个新进程的fork系统调用,然后用于实现进程自我终止的exit系统调用;改变进程原有代码的exec系统调用;用于将调用进程挂起并等待子进程终止的wait系统调用;获得进程标识符的getpid系统调用等处理过程。
(2)什么是进程同步?wait( )是如何实现进程同步的?a.我们把异步环境下的一组并发进程因直接制约而互相发送消息、进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。
b.首先程序在调用fork()建立一个子进程后,马上调用wait(),使父进程在子进程调用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步。
五、实验总结通过进程创建和进程控制两节课实验,让我们掌握了进程的基本概念及其含义,了解了系统是怎样创建进程的,首次调用新进程时,其入口地址在哪,应该开始从哪执行;搞明白可执行文件加载时进行的那些处理,进一步深刻认识到进程同步的概念以及wait()实现进程同步的方式方法。
六、参考程序#include<stdio.h>#include<unistd.h>main( ){int pid;pid=fork( ); /*创建子进程*/switch(pid){case -1: /*创建失败*/printf("fork fail!\n");exit(1);case 0: /*子进程*/ execl("/bin/ls","ls","-1","-color",NULL); printf("exec fail!\n");exit(1);default: /*父进程*/ wait(NULL); /*同步*/printf("ls completed !\n");exit(0);}}。
实验2 进程控制一、实验目的加深对进程概念的理解,明确进程和程序和区别;进一步认识并发执行的实质;分析进程争用资源的现象。
二、实验内容1. 熟悉Linux进程控制常用命令。
2. 输入进程创建、控制的程序并调试程序。
三、实验预备知识1. 进程控制常用命令(1)ps 命令功能:查看目前的系统中有哪些进程,以及它们的执行情况。
常用命令格式及功能如下:ps 查看系统中属于自己的进程ps au 查看系统中所有用户的进程ps aux 查看系统中包含系统内部的及所有用户的进程主要输出列说明:USER:进程所有者的用户名PID:进程号TTY:进程从哪个终端启动TIME:此进程所消耗的CPU时间COMMAND:正在执行的命令或进程名称(2)top 命令功能:动态显示进程,实时监测进程状态。
与ps命令相似,只是top命令在执行后会以指定的时间间隔来刷新显示信息,以使top所显示的进程状态总是当前时刻的。
(3)kill 命令功能:结束或终止进程。
常用命令格式及功能如下:kill 5302 杀死PID为5302的进程kill -9 5302 强行杀死PID为5302的进程(4)echo $变量名功能:查看外壳变量的设定值。
例:echo $$ 显示当前进程PID2.常用系统调用函数常用系统调用函数、程序的说明、参数及定义如下:(1)fork()函数功能:创建一个新进程函数格式:int fork()其中返回int取值意义如下:小于0:创建失败0: 创建成功,在子进程中返回0值大于0: 创建成功,在父进程中返回子进程id值-1:创建失败(2)wait()函数功能:父进程等待子进程终止,以便对子进程进行善后处理。
函数格式:int wait(int *statloc)参数定义:statloc 指出子进程终止状态码的位置。
若不关心子进程的终止状态,可传递一个空指针。
返回值:正常返回时,为终止子进程的PID;错误返回时为-1;其他为0。
实验二进程控制1.学时:2,课外学时8。
2.实验类型:设计性实验3.实验目的:(1)加深对进程概念的理解,明确进程与程序的区别。
(2)进一步认识并发执行的实质。
(3)分析进程争用资源的现象,学习解决进程互斥的方法。
(4)熟悉linux下gcc工具的使用4.实验内容:题目一 4个fork。
写出以下程序输出结果,并画出进程家族树(必须编号)。
#include <unistd.h>int main(void){fork();fork();fork();fork();putchar('A');}题目二父进程不创建孙子进程。
如果父进程需要创建3子进程,但不想创建孙子进程。
编写程序,并画出进程家族树。
题目三父进程创建4个进程。
如果父进程需要创建4个进程,画出所有可能进程家族树。
题目四进程创建。
编写一段程序,使用系统调用fork()创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示“a“;两个子进程分别显示字符”b“和字符“c”。
试观察记录屏幕上的显示结果,并分析原因。
题目五子进程利用exec函数执行特定操作。
用fork( )创建一个进程,再调用exec( )用新的程序替换该子进程的内容;利用wait( )来控制进程执行顺序。
5.实验指导一)所涉及的系统调用1.fork( )创建一个新进程。
系统调用格式:pid=fork( )参数定义:fork( )返回值意义如下:0:在子进程中,pid变量保存的fork( )返回值为0,表示当前进程是子进程。
>0:在父进程中,pid变量保存的fork( )返回值为子进程的id值(进程唯一标识符)。
-1:创建失败。
如果fork( )调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork( )被调用了一次,但返回了两次。
此时OS在内存中建立一个新进程,所建的新进程是调用fork( )父进程(parent process)的副本,称为子进程(child process)。
实验一、进程控制实验1.1 实验目的加深对于进程并发执行概念的理解。
实践并发进程的创建和控制方法。
观察和体验进程的动态特性。
进一步理解进程生命期期间创建、变换、撤销状态变换的过程。
掌握进程控制的方法,了解父子进程间的控制和协作关系。
练习 Linux 系统中进程创建与控制有关的系统调用的编程和调试技术。
1.2 实验说明1)与进程创建、执行有关的系统调用说明 进程可以通过系统调用fork()创建子进程并和其子进程并发执行.子进程初始的执行映像是父进程的一个复本.子进程可以通过 exec()系统调用族装入一个新的执行程序。
父进程可以使用 wait()或 waitpid()系统调用等待子进程的结束并负责收集和清理子进程的退出状态。
fork()系统调用语法:pid_t#include <unistd.h>fork(void);fork 成功创建子进程后将返回子进程的进程号,不成功会返回-1.exec 系统调用有一组 6 个函数,其中示例实验中引用了 execve 系统调用语法:#include <unistd.h>const char * envp[]);path 要装const char *argv[],int execve(const char *path,入的新的执行文件的绝对路径名字符串.argv[] 要传递给新执行程序的完整的命令参数列表(可以为空).envp[] 要传递给新执行程序的完整的环境变量参数列表(可以为空).Exec 执行成功后将用一个新的程序代替原进程,但进程号不变,它绝不会再返回到调用进程了。
如果 exec 调用失败,它会返回-1。
wait() 系统调用语法:#include <sys/types.h>pid_t#include <sys/wait.h>wait(int *status);status 用pid_t waitpid(pid_t pid,int *status,int option);于保留子进程的退出状态pid 可以为以下可能值:-1 等待所有 PGID 等于 PID 的绝对值的子进程1 等待所有子进程0 等待所有 PGID 等于调用进程的子进程>0 等待 PID 等于 pid 的子进程 option 规定了调用 waitpid 进程的行为:WNOHANG 没有子进程时立即返回WUNTRACED 没有报告状态的进程时返回wait 和 waitpid 执行成功将返回终止的子进程的进程号,不成功返回-1。
电大操作系统实验2:进程管理实验
实验目的:
1.加深对进程概念的理解,特别是进程的动态性和并发性。
2.了解进程的创建和终止。
3.学会查看进程的状态信息。
4.学会使用进程管理命令。
实验要求:
1.理解有关进程的概念,能够使用ps命令列出系统中进
程的有关信息并进行分析。
2.理解进程的创建和族系关系。
3.能够使用&,jobs,bg,at等命令控制进程的运行。
实验内容:
1.使用ps命令查看系统中运行进程的信息。
实验环境:
实验步骤和结果:
1.输入ps命令,可以报告系统当前的进程状态。
2.输入ps-e命令,可以显示系统中运行的所有进程,包括系统进程和用户进程。
3.输入ps-f命令,可以得到进程的详细信息。
进程控制:
1.后台进程
1) $grep "注册用户名" /etc/passwd。
/tmp/abc &
2.作业控制
1) 进程休眠60秒Sleep 60 &
2) 进程休眠30秒Sleep 30 &
3) 查看进程状态Jobs
4) 将睡眠30秒的sleep命令放在前台执行fg%2
3.发送中断信号
1) 后台运行sleep命令$sleep 120 &
2) 查看sleep进程的状态$ps-p pid
3) 终止sleep命令$kill -9 pid。
实验二:进程的控制1 .实验目的通过进程的创建、撤消和运行加深对进程概念和进程并发执行的理解,明确进程与程序之间的区别。
进程概念和程序概念最大的不同之处在于:(1)进程是动态的,而程序是静态的。
(2)进程有一定的生命期,而程序是指令的集合,本身无“运动”的含义。
没有建立进程的程序不能作为1个独立单位得到操作系统的认可。
(3)1个程序可以对应多个进程,但1个进程只能对应1个程序。
进程和程序的关系犹如演出和剧本的关系。
(4)进程和程序的组成不同。
从静态角度看,进程由程序、数据和进程控制块(PCB)三部分组成。
而程序是一组有序的指令集合。
2 .实验内容(1) 了解系统调用fork()、execvp()和wait()的功能和实现过程。
(2) 编写一段程序,使用系统调用fork()来创建两个子进程,并由父进程重复显示字符串“parent:”和自己的标识数,而子进程则重复显示字符串“child:”和自己的标识数。
(3) 编写一段程序,使用系统调用fork()来创建一个子进程。
子进程通过系统调用execvp()更换自己的执行代码,新的代码显示“new program.”。
而父进程则调用wait()等待子进程结束,并在子进程结束后显示子进程的标识符,然后正常结束。
3 .实验步骤(1)gedit创建进程1.c(2)使用gcc 1.c -o 1编译并./1运行程序1.c#include<stdio.h>#include<sys/types.h>#include<unistd.h>#include<sys/wait.h>void main(){int id;if (fork()==0){printf("child id is %d\n",getpid());}else if (fork()==0){printf("child2 id is %d\n",getpid());}else{id=wait(NULL);printf("parent id is %d\n",getpid());}}(3)运行并查看结果(4)gedit创建进程2.c使用gcc 2.c -o 2编译并./2运行程序2.c1 #include<stdio.h>2 #include<stdlib.h>3 #include<sys/types.h>4 #include<unistd.h>5 #include<sys/wait.h>6 int main()7 {8 pid_t pid;9 char *a[]={"ls","-l","/etc/passwd",0};10 int result;11 pid=fork();12 if(pid<0)13 {printf("fork error!");}14 else if(pid==0)15 {16 printf("new program!\n");17 execvp("ls",a);18 exit(0);19 }20 else21 {22 int e=waitpid(pid,&result,0);23 printf("child peocess PID:%d\n",e);24 exit(0);25 }26 }(5)运行并查看结果4 .思考(1)系统调用fork()是如何创建进程的?1)申请空白PCB 2)为新进程分配资源3)初始化进程控制块(初始化标识信息,初始化处理机状态信息,初始化处理机控制信息,)4)将新进程插入就绪队列(2)当首次将CPU 调度给子进程时,其入口在哪里?进程的进程控制块(PCB)结构中有指向其TTS(任务状态段)的指针,TTS里面存放着进程的入口。
实验进程管理(一)进程的创建实验实验目的1、掌握进程的概念,明确进程的含义2、认识并了解并发执行的实质实验内容1、编写一段程序,使用系统调用fork()创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。
试观察记录屏幕上的显示结果,并分析原因。
2、修改上述程序,每一个进程循环显示一句话。
子进程显示'daughter…'及'son ……',父进程显示'parent ……',观察结果,分析原因。
实验准备(1)阅读LINUX的fork.c源码文件(见附录二),分析进程的创建过程。
(2)阅读LINUX的sched.c源码文件(见附录三),加深对进程管理概念的认识。
实验指导一、进程UNIX 中,进程既是一个独立拥有资源的基本单位,又是一个独立调度的基本单位。
一个进程实体由若干个区(段)组成,包括程序区、数据区、栈区、共享存储区等。
每个区又分为若干页,每个进程配置有唯一的进程控制块PCB,用于控制和管理进程。
PCB 的数据结构如下:1、进程表项(Process Table Entry)。
包括一些最常用的核心数据:进程标识符PID、用户标识符UID、进程状态、事件描述符、进程和U区在内存或外存的地址、软中断信号、计时域、进程的大小、偏置值nice、指向就绪队列中下一个PCB 的指针P_Link、指向U 区进程正文、数据及栈在内存区域的指针。
2、U 区(U Area)。
用于存放进程表项的一些扩充信息。
每一个进程都有一个私用的U区,其中含有:进程表项指针、真正用户标识符u-ruid(read user ID)、有效用户标识符u-euid(effective user ID)、用户文件描述符表、计时器、内部I/O参数、限制字段、差错字段、返回值、信号处理数组。
步骤一:进程的创建
仔细观察可以发现每次执行结果中进程的执行顺序是不定的,从进程并发执行来看,输出bca,acb等都有可能。
fork()创建进程所需的时间要多于输出一个字符的时间,因此在住进程创建进程2的同时,进程1就输出了“b”,而进程2和主进程的输出次序是随机性的,所以会出现上述结果。
步骤二:进程的控制
因为是在实验1的基础上进行的,所以,操作步骤与实验1差不多。
由于函数printf()输出的字符串之间不会被中断,因此字符串内部的字符顺序输出时不变。
但是,由于进程并发执行时调度顺序和父子进程的抢占处理机问题,输出字符串和先后顺序随着执行的不同而变化。
这与打印单字符的结果相同。
步骤三:管道通信
实现进程的管道通信。
使用系统调用pipe()建立一条管道线;两个子进程p1和p2分别向管道个写一句话:
Child 1 is sending a message!
Child 2 is sending a message!
而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。
实验二模拟实现进程管理组长:李和林软件1402一、实验目的1.理解进程的概念,明确进程和程序的区别。
2.理解并发执行的实质。
3.掌握进程的创建,睡眠,撤销等进程控制方法。
二、实验内容用C语言,JAVA语言,C++语言编写程序,模拟实现创建新的进程;查看运行进程,换出某个进程;杀死运行进程。
三、实验准备1.进程的定义进程是程序在一个数据集合上的运行过程,是系统资源分配和调度的一个独立单位。
一个程序在不同的数据集合上运行,乃至一个程序在同样数据集合上的多次运行都是不同的进程。
2.进程的状态通常情况下,一个进程必须具有就绪,执行和阻塞三种基本情况。
1)就绪状态当进程已分配到除处理器外的所有必要资源后,只要再获得处理器就可以立即执行,这时进程的状态就为就绪状态。
在一个系统里,可以有多个进程同时处于就绪状态,通常把这些就绪进程排成一个或多个队列,称为就绪队列。
2)执行状态处于就绪状态的进程一旦获得处理器,就可以运行,进程状态也就处于执行状态,在单处理器系统中,只能有一个进程处于执行状态,在多处理器系统中,则可能有多个进程处于执行状态3)阻塞状态正在执行的进程因为发生某些事件而暂停运行,这种受阻暂停的状态称为阻塞状态,也可称为等待状态。
通常将处于阻塞状态的进程拍成一个队列,称为阻塞队列,在有些系统中,也会按阻塞原因的不同将阻塞状态的进程排成多个队列。
3.进程状态之间的转换4.进程控制块1)进程控制块的作用进程控制块是进程实体的重要组成部分,主要包含下述四个方面的信息:a)进程标示信息b)说明信息c)现场信息d)管理信息5.进程控制块的组织方式1)链接方式2)索引方式6.进程控制原语1)创建原语2)撤销原语3)阻塞原语4)唤醒原语7.程序代码#include<stdio.h>#include<iostream>using namespace std;void clrscr();void create();void run( );void exchange( );//唤出void kill( );void wakeUp( );//唤醒struct process_type{int pid;int priority;//优先次序int size;int state;//状态char info[10];};struct process_type internalMemory[20];int amount=0,hangUp=0,pid,flag=0;//数目,挂起void main( ){int n;int a;n=1;clrscr( );while(n==1){cout<<"\n********************************************";cout<<"\n* 进程演示系统 *";cout<<"\n********************************************";cout<<"\n 1.创建新的进程 2.查看运行进程 ";cout<<"\n 3.换出某个进程 4.杀死运行进程 ";cout<<"\n 5.唤醒某个进程¨ 6.退出系统 ";cout<<"\n*********************************************"<<endl;cout<<"请选择 ";cin>>a;switch(a){case 1:create( );break;case 2:run( );break;case 3:exchange();//换出break;case 4:kill();break;case 5:wakeUp();break;case 6:exit(0);default:n=0;}}}void create(){ //创建进程int i=0;if (amount>=20){cout<<" 内存已满,请先结束或换出进程";}else{for (i=0;i<20;i++){if (internalMemory[i].state==0){break;}}cout<<"请输入新进程的pid: "<<endl;cin>>internalMemory[ i ].pid;cout<<"请输入新进程的优先级: "<<endl;cin>>internalMemory[amount].priority;cout<<"请输入新进程的大小: "<<endl;cin>>internalMemory[amount].size;cout<<"请输入新进程的内容: "<<endl;cin>>internalMemory[amount].info;internalMemory[i].state=1;amount++;}}void clrscr()//清除内存空间{for (int i=0;i<19;i++){internalMemory[i].pid=0;internalMemory[i].priority=0;internalMemory[i].size=0;internalMemory[i].state=0;}amount=0;}void run(){for (int i=0;i<20;i++){if (internalMemory[i].state==1){cout<<"当前内存中的进程:\n"<<endl;cout<<"当前运行的进程: ";cout<<internalMemory[i].pid<<endl;cout<<"当前运行进程的优先级: ";cout<<internalMemory[i].priority<<endl;cout<<"当前运行进程占用的空间大小: ";cout<<internalMemory[i].size;}}}void exchange( ){//唤出优先级最小的进程if (!amount){cout<<"当前没有运行进程\n";return;}cout<<"\n输入换出进程的ID值: ";cin>>pid;for (int i=0;i<20;i++){if (pid==internalMemory[i].pid){if (internalMemory[i].state==1){internalMemory[i].state=2;hangUp++;cout<<"\n已经成功换出进程\n";}else if (internalMemory[i].state==0){cout<<"\n要换出的进程不存在";}else{cout<<"\n要换出的进程已被挂起\n";}flag=1;break;}}if (flag==0){cout<<"\n要换出的进程不存在";}}void kill( ){if (!amount){cout<<"当前没有运行进程\n";return;}cout<<"请输入要杀死的进程: ";cin>>pid;for (int i=0;i<20;i++){if (pid==internalMemory[i].pid){if (internalMemory[i].state==1){internalMemory[i].state=0;amount--;cout<<"此进程被杀死"<<pid;}else if (internalMemory[i].state==0){cout<<"\n要杀死的进程不存在\n";}else{cout<<"\n要杀死的进程已被挂起\n";}flag=1;break;}}if (!flag){cout<<"\n要杀死的进程不存在\n";}}void wakeUp(){if (!amount){cout<<"当前没有运行进程"<<endl;return;}if (!hangUp){cout<<"当前没有挂起进程";return;}cout<<"请输入pid: ";cin>>pid;for (int i=0;i<20;i++){if (pid==internalMemory[i].pid){flag=0;if (internalMemory[i].state==2){internalMemory[i].state=1;hangUp--;cout<<"已经成功唤醒进程\n";}else if (internalMemory[i].state==0){cout<<"\n要换醒的进程不存在\n";}else{cout<<"\n要唤醒的进程已被挂起\n";}break;}}if (flag){cout<<"\n要唤醒的进程已被挂起\n"<<endl;}}8.实现的结果。
实操作业二进程控制
进程控制是操作系统中的一个重要概念,它涉及到对进程的创建、执行、调度、终止等操作。
通过进程控制,操作系统可以实现对系统资源的
分配和管理,提高系统的效率和可靠性。
在本文中,将详细介绍进程的创建、执行、调度和终止的相关内容。
1.进程创建
进程的创建是指通过操作系统的创建进程的系统调用,创建一个新的
进程。
在进程创建过程中,操作系统需要进行以下几个步骤:
1.1分配内存空间:操作系统为新的进程分配内存空间,用于存储进
程的代码、数据和堆栈信息。
1.2初始化PCB:操作系统通过调用PCB(进程控制块)数据结构来
管理进程,所以在创建进程时,需要初始化进程的PCB,记录进程的状态、优先级、资源使用情况等信息。
1.3分配进程号:每个进程都有一个唯一的进程号(PID),用于系
统对进程的标识和管理,所以在创建进程时,操作系统需要为新的进程分
配一个进程号。
进程控制实验报告进程控制实验报告一、实验目的本实验旨在通过实际操作,深入理解进程控制的概念、原理和实现方式,掌握进程控制的技巧和方法,提升解决实际问题的能力。
二、实验原理进程控制是操作系统内核的重要功能之一,它负责协调和管理系统中多个进程的执行顺序和资源分配。
进程控制的主要任务包括创建和终止进程、进程切换和进程同步等。
本实验将通过具体的操作,学习和体验进程控制的过程和细节。
三、实验步骤1.实验准备(1)了解和熟悉实验室环境,包括计算机硬件配置、操作系统版本等信息。
(2)准备实验材料,包括相关文档、软件工具等。
(3)明确实验任务和目的,制定实验计划。
2.创建进程(1)打开实验环境,启动操作系统。
(2)使用编程语言(如C语言)编写一个简单的程序,该程序将创建一个新的进程。
(3)编译并运行程序,观察和记录进程的创建过程。
3.进程切换(1)编写一个程序,该程序将在两个进程之间进行切换。
(2)运行程序,观察和记录进程切换的过程和效果。
4.进程同步(1)使用信号量或其他同步机制实现两个进程的同步。
(2)运行程序,观察和记录进程同步的过程和效果。
5.进程终止(1)编写一个程序,该程序将终止一个指定的进程。
(2)运行程序,观察和记录进程终止的过程和效果。
6.实验总结与报告编写(1)总结实验过程和结果,梳理实验中的问题和解决方法。
(2)编写实验报告,包括实验目的、原理、步骤、结果分析等。
四、实验结果与分析通过本次实验,我们成功地创建了一个新的进程,并实现了进程之间的切换、同步和终止。
在实验过程中,我们深入理解了进程控制的概念、原理和实现方式,掌握了进程控制的技巧和方法。
同时,我们也遇到了一些问题,如进程创建失败、进程切换不成功等,但通过仔细分析问题原因并采取相应的解决方法,最终成功解决了这些问题。
通过本次实验,我们不仅学到了专业知识,也提高了解决实际问题的能力。
五、实验结论与建议本次实验让我们更加深入地理解了进程控制的相关知识,并掌握了进程控制的基本操作方法。
### 实验目的1. 理解操作系统进程控制的基本概念和原理。
2. 掌握进程的创建、同步、通信和终止等操作。
3. 熟悉Linux系统中的进程控制命令和系统调用。
4. 理解进程调度算法的基本原理和实现方法。
### 实验环境1. 操作系统:Linux2. 编程语言:C/C++3. 编译器:gcc4. 开发工具:vim### 实验内容本实验主要涉及以下内容:1. 进程的创建与终止2. 进程同步与通信3. 进程调度算法#### 1. 进程的创建与终止实验一:利用fork()创建进程```c#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>int main() {pid_t pid;pid = fork();if (pid < 0) {printf("fork() error\n");return 1;} else if (pid == 0) {printf("Child process, PID: %d\n", getpid()); printf("Child process is running...\n");sleep(2);printf("Child process is exiting...\n");return 0;} else {printf("Parent process, PID: %d\n", getpid()); printf("Parent process is running...\n");sleep(3);printf("Parent process is exiting...\n");wait(NULL);}return 0;}```实验二:利用exec()创建进程```c#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>int main() {pid_t pid;pid = fork();if (pid < 0) {printf("fork() error\n");return 1;} else if (pid == 0) {execlp("ls", "ls", "-l", (char )NULL); printf("execlp() error\n");return 1;} else {wait(NULL);}return 0;}```实验三:进程终止```c#include <stdio.h>#include <sys/types.h>#include <sys/wait.h>int main() {pid_t pid;pid = fork();if (pid < 0) {printf("fork() error\n");return 1;} else if (pid == 0) {printf("Child process, PID: %d\n", getpid()); sleep(2);printf("Child process is exiting...\n");exit(0);} else {wait(NULL);}return 0;}```#### 2. 进程同步与通信实验四:使用信号实现进程同步```c#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <signal.h>int main() {pid_t pid;int status;int signalNo = 1;pid = fork();if (pid < 0) {printf("fork() error\n");return 1;} else if (pid == 0) {printf("Child process, PID: %d\n", getpid()); while (1) {pause();printf("Child process is running...\n"); }} else {printf("Parent process, PID: %d\n", getpid()); sleep(1);kill(pid, signalNo);wait(NULL);}return 0;}```实验五:使用管道实现进程通信```c#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>int main() {int pipefd[2];pid_t pid;char buffer[100];if (pipe(pipefd) == -1) {printf("pipe() error\n"); return 1;}pid = fork();if (pid < 0) {printf("fork() error\n"); return 1;} else if (pid == 0) {close(pipefd[0]);read(pipefd[1], buffer, sizeof(buffer));printf("Child process, PID: %d, Received: %s\n", getpid(), buffer);} else {close(pipefd[1]);write(pipefd[0], "Hello, Child!\n", 14);wait(NULL);}return 0;}```#### 3. 进程调度算法实验六:先来先服务(FCFS)调度算法```c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#define NUM_PROCESSES 5#define TIME_QUANTUM 2typedef struct {int pid;int arrival_time;int burst_time;} Process;int main() {Process processes[NUM_PROCESSES] = {{1, 0, 5},{2, 1, 3},{3, 2, 4},{4, 3, 2},{5, 4, 1}};int i, j, time = 0, completed = 0;int wait_time[NUM_PROCESSES], turnaround_time[NUM_PROCESSES]; // Calculate waiting timefor (i = 0; i < NUM_PROCESSES; i++) {wait_time[i] = 0;}for (i = 0; i < NUM_PROCESSES; i++) {for (j = 0; j < i; j++) {wait_time[i] += processes[j].burst_time;}}// Calculate turnaround timefor (i = 0; i < NUM_PROCESSES; i++) {turnaround_time[i] = wait_time[i] + processes[i].burst_time;}// Calculate average waiting time and turnaround timeint total_wait_time = 0, total_turnaround_time = 0;for (i = 0; i < NUM_PROCESSES; i++) {total_wait_time += wait_time[i];total_turnaround_time += turnaround_time[i];}printf("Average waiting time: %.2f\n", (float)total_wait_time / NUM_PROCESSES);printf("Average turnaround time: %.2f\n",(float)total_turnaround_time / NUM_PROCESSES);return 0;}```实验七:时间片轮转调度算法```c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#define NUM_PROCESSES 5#define TIME_QUANTUM 2typedef struct {int pid;int arrival_time;int burst_time;} Process;int main() {Process processes[NUM_PROCESSES] = {{1, 0, 5},{2, 1, 3},{3, 2, 4},{4, 3, 2},{5, 4, 1}};int i, j, time = 0, completed = 0;int wait_time[NUM_PROCESSES], turnaround_time[NUM_PROCESSES]; // Calculate waiting timefor (i = 0; i < NUM_PROCESSES; i++) {wait_time[i] = 0;}for (i = 0; i < NUM_PROCESSES; i++) {for (j = 0; j < i; j++) {wait_time[i] += processes[j].burst_time;}}// Calculate turnaround timefor (i = 0; i < NUM_PROCESSES; i++) {turnaround_time[i] = wait_time[i] + processes[i].burst_time;}// Calculate average waiting time and turnaround timeint total_wait_time = 0, total_turnaround_time = 0;for (i = 0; i < NUM_PROCESSES; i++) {total_wait_time += wait_time[i];total_turnaround_time += turnaround_time[i];}printf("Average waiting time: %.2f\n", (float)total_wait_time / NUM_PROCESSES);printf("Average turnaround time: %.2f\n",(float)total_turnaround_time / NUM_PROCESSES);return 0;}```### 实验总结通过本次实验,我对操作系统进程控制有了更深入的了解。
实验2:进程控制实验指导一、实验目的和要求1. 熟练使用Linux的C语言开发环境2. 学习并掌握Linux 编译工具gcc 的使用方法3. Linux操作系统下的熟悉并能够进行进程创建4. 掌握Linux操作系统下的并发进程间同步具体完成:二、实验指导1. 练习使用Linux 编辑器Vi,为输入源程序做准备。
利用Vi 编辑器完成例程的输入、编译、运行。
例程:#include <linux/unistd.h>int main( ){int i=getuid( ) ;printf(“Hello world! This is my uid: %d\\n”, i ) ;}2. vi编辑器常用命令(见下表)。
进入Vi编辑器:$vi 文件名↙3. 编译工具gccRed Hat Linux的编译器是gcc。
gcc软件包支持C、C++。
gcc的可执行文件在/usr/bin/gcc下,/lib和/usr/lib目录下是库文件。
/usr/include目录下是头文件。
gcc编译常用格式为:$gcc 源文件名↙(例如:$gcc aaa.c↙,将生成默认可执行文件a.out)或者 $gcc -o 目标文件名源文件名↙(例如:$gcc –o aaa aaa.c)4. 通过进程创建的应用实例,深刻理解进程创建的过程将以下例题输入运行,并分析运行结果#include <stdio.h>#include <sys/types.h>#include <unistd.h>int main(void){pid_t pid;int data=5;if((pid=fork())<0){printf("fork error\n");exit(0);}else if(pid==0){data--;printf("child\'s data is:%d\n",data);exit(0);}else{printf("parent\'s data is:%d\n",data);}exit(0);}5. 通过fork( )、wait( )、exit( )等实现进程创建、并发和同步。
进程的管理和控制实验报告实验目的:本实验旨在了解进程的管理和控制,掌握进程的创建、终止和状态转换等操作,并通过实际的代码编写和运行实验,加深对进程管理的理解。
实验原理:在操作系统中,进程是执行中的程序的实例。
进程管理涉及到创建新进程、终止现有进程、管理进程的状态等操作。
进程的创建:进程的创建可以通过系统调用fork()来完成。
fork()系统调用会创建一个新的进程,称为子进程,子进程将继承父进程的代码、数据和资源。
通过fork()的返回值来区分父子进程,父进程返回子进程的进程ID,子进程返回0。
进程的终止:进程的终止可以通过系统调用exit()来完成。
exit()系统调用会终止当前进程的执行,并返回一个退出状态码。
一个进程的终止也可以由其他进程通过发送终止信号来实现。
进程的状态转换:进程在执行过程中会经历不同的状态,包括就绪态、运行态、阻塞态等。
进程的状态转换可以通过系统调用来实现。
例如,当进程被阻塞时,可以通过系统调用sleep()将其状态转换为阻塞态,当等待的事件发生时,再将其状态转换为就绪态。
实验步骤:1. 编写一个简单的程序,包含进程的创建、终止和状态转换等操作。
2. 使用fork()系统调用创建子进程,并在子进程中执行一段代码。
3. 在父进程中对子进程进行管理,包括等待子进程的终止和获取子进程的退出状态码。
4. 在子进程中通过exit()系统调用终止进程的执行。
5. 在父进程中通过wait()系统调用等待子进程的终止,并获取子进程的退出状态码。
6. 在子进程中通过系统调用sleep()将进程的状态转换为阻塞态。
7. 在父进程中发送终止信号给子进程,观察子进程的终止情况。
实验结果与分析:经过实验,我们成功地创建了子进程并在子进程中执行了一段代码。
父进程能够正确地等待子进程的终止并获取子进程的退出状态码。
在子进程中使用sleep()系统调用后,观察到子进程的状态转换为阻塞态。
当父进程发送终止信号给子进程时,子进程能够正确地终止执行。
计算机操作系统实训教程实验报告
姓名王学杰专业计算机应用技术班级1362班
课程操作系统实验项目进程的控制
【实验目的】
1、掌握在子进程中使用execl()执行系统命令或调用已编译的其他程序。
2、掌握子进程通过创建子进程完成某项任务的方法。
3、掌握系统调用的exit()和_exit()的使用
【实验要求】
设计程序实现父进程创建多个子进程,子进程中使用execl()函数调用已编译的其他可执行程序。
【实验内容】
程序execl.c的子进程利用execl()函数调用可执行程序段jie.c 程序一/*execl.c*/
# include <unistd.h>
# include <stdio.h>
# include <errno.h>
void main()
{
int p;
p=fork();
if(p>0)
{
printf("I an parent!\n");
printf("I think the best fruit is apple!!!\n" );
}
printf("\n");
else
{
printf("**********before execute execl**********\n");
execl("./jie","jie",NULL);
perror("execl failed to run jie\n");
printf("**********after execute execl**********\n");
}
}
程序二/*jie.c*/
# include <stdio.h>
void main()
{
printf("I an child!\n");
printf("I think the best fruit is watermelon!!!\n");
}
实验相关截图
实验结果
【实验总结】
一、exec函数族
1.exec家族一共有六个函数,分别是:
(1)int execl(const char *path, const char *arg, ......);
(2)int execle(const char *path, const char *arg, ...... , char * const envp[]);
(3)int execv(const char *path, char *const argv[]);
(4)int execve(const char *filename, char *const argv[], char *const envp[]);
(5)int execvp(const char *file, char * const argv[]);
(6)int execlp(const char *file, const char *arg, ......);
其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。
这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。
看上去还是旧的躯壳,却已经注入了新的灵魂。
只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。