进程控制实验

  • 一、实验目的:
  • 二、实验平台:
  • 三、实验内容:
    • 1.进程的创建与销毁
      • 进程控制相关函数
    • 实验结果分析
    • 2.多进程并发执行
      • time命令
    • 实验结果分析
  • 四、总结分析

一、实验目的:

加深对进程概念的理解,明确进程和程序的区别;掌握Linux操作系统的进程创建和终止操作,体会父进程和子进程的关系及进程状态的变化;进一步认识并发执行的实质,编写并发程序。

二、实验平台:

虚拟机:VMWare15.5.1
操作系统:CentOS7 64位
编辑器:Vim
编译器:Gcc

三、实验内容:

1.进程的创建与销毁

编写一段程序,使用系统调用fork()创建两个子进程,当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示“身份信息”:父进程显示“Parent process! PID=xxx1 PPID=xxx2”;子进程显示“Childx process! PID=xxx PPID=xxx”。多运行几次,观察记录屏幕上的显示结果,并分析原因。
说明:
xxx1为进程号,用getpid()函数可获取进程号;
xxx2为父进程号,用getppid()函数可获取父进程号;
Childx中x为1和2,用来区别两个子进程;
wait()函数用来避免父进程在子进程终止之前终止。
实验主要代码:

//print.c
#include<stdio.h>
int main(int argc,char *argv[])
{for(int i=0;i<argc;i++){printf("argv[%d]=%s\n",i,argv[i]);}printf("i am print.c,i am executed\n");return 0;
}
//example1.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void)
{pid_t pid=fork();if(pid==0){   printf("Child1 process! PID=%d  PPID=%d \n",getpid(),getppid()); if(execl("./print","print","hello",NULL)==-1) printf("execl failed!");    printf("where am I?");}else if(pid>0){pid_t pid2=fork();if(pid2==0){printf("Child2 process! PID=%d  PPID=%d \n",getpid(),getppid());}else if(pid2>0){wait();printf("Parent process! PID=%d  PPID=%d \n",getpid(),getppid()); exit(0);}else{printf("fork faild\n");exit(0);}}else{printf("fork faild\n");exit(0);}
}

实验过程:编辑print.c和example1.c两个文件,输入命令行对.c文件进行编译输出。
编译过程:#gcc print.c –o print
#gcc example1.c –o example1
运行截图如下:

进程控制相关函数

1.fork()
用于创建一个新进程(子进程)。
函数原型:
#include <unistd.h>
pid_t fork(void);
返回:子进程中为0,父进程中为子进程ID,出错为-1。
子进程被创建后就进入就绪队列和父进程分别独立地等待调度。子进程继承父进程的程序段代码,子进程被调度执行时,也会和父进程一样从fork()返回。
从共享程序段代码的角度来看,父进程和子进程所执行的程序代码是同一个,在内存中只有一个程序副本;
但是从编程的角度来看,为了使子进程和父进程做不同的事,需要在程序中区分父进程和子进程的代码段。这需要借助于fork()的返回值来标志当前进程的身份。从fork()返回后,都会执行语句:pid=frok();
得到返回值pid有三种情况,分别对应出错(小于0)、在父进程中(大于0)、在子进程中(等于0)。
由于父进程和子进程各自独立地进入就绪队列等待调度,所以谁会先得到调度是不确定的,这与系统的调度策略和系统当前的资源状态有关。因此谁会先从fork()返回并继续执行后面的语句也是不确定的。

2.wait()
查询子进程的退出状态(即正常退出的退出码或导致异常终止的信号),并回收子进程的内核资源。
函数原型:
#include <sys/wait.h>
pid_t wait(int * status);
返回值:若成功则返回进程ID,若出错则返回-1。
Wait()函数常用来控制父进程和子进程的同步。在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发送SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()函数返回继续执行原程序。

3. exit()
exit()是进程结束最常调用的函数,在main()函数中调用return,最终也是调用exit()函数。这些都是进程的正常终止。在正常终止时,exit()函数返回进程结束状态。
函数原型:
#include<stdio.h>
void exit(int status)
从OS角度来看,进程终止会释放进程用户空间的所有资源,而进程描述符并不释放,它将来由其父进程回收。若父进程先于子进程终止,子进程成为“孤儿进程”,“孤儿进程”会被init进程(进程号为1)领养;若子进程先于父进程终止,子进程成为“僵尸进程”,父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍占用的资源)。
程序可以执行到main()的最后一个“}“结束,也可以运行exit();结束,也可以运行到return 0;结束。

4.execl()
系统调用execl()可以将新程序加载到某一进程的内存空间,该进程会从新程序的main()函数开始执行。
函数原型:
#include <unistd.h>
int execl (const char * pathname, const char * arg0,…/*(char*)0*/)
pathname是要加载程序的全路径名,arg0及以后为参数列表。
进程的用户内存空间被替换,而进程的其他属性基本不改变。进程完整的内存空间:正文区、堆区、栈区、数据区都被替换,原内容不存在了。代码替换完后,在execl()后面的代码毫无意义。

实验结果分析

先后四次运行,根据输出分析实验结果:

①每次运行创建的子进程Childx process的PPID均为父进程Parent process的PID,说明两个子进程均为同一父进程创建。

②每次运行的父进程Parent process的PPID均为3105,说明父进程也以子进程的形式存在,其父进程为同一系统进程。

③我们注意第一个if代码段,调用了execl()函数,将当前进程child1替换掉,所以之后的"where am I?”字符串并没有被输出,child1进程从print程序的main()开始执行,输出两个传参以及一段字符串,最终在main()的return 0;后结束。

④进程创建后由于父进程和子进程各自独立地进入就绪队列等待调度,所以谁会先得到调度是不确定,实验数据可以看出child1进程先运行和child2进程先运行各出现两次。

⑤父进程代码段因为调用了wait()函数,等待子进程结束后函数返回继续执行原程序,输出相应信息,所以父进程字符串最后才输出。

2.多进程并发执行

fork()和exec()系列函数能同时运行多个程序,利用上述函数将下面单进程顺序执行的程序single.c改造成可并发执行3个进程的程序multi_process.c;并用time命令获取程序的执行时间,比较单进程和多进程运行时间,并分析原因。

//single.c
#include <stdio.h>
#define NUM 5
int main(void)
{ void print_msg(char *m); print_msg("Good "); print_msg("Morning  "); print_msg("007\n");  //将007替换为本人学号return 0;
}
void print_msg(char *m)
{ int i; for(i = 0; i<NUM; i++){ printf("%s",m); fflush(stdout); sleep(1);}
}

编译过程:#gcc single.c –o single
运行截图如下:

结果分析:单进程执行按次序依次打印五次三个字符串。
创建多个进程代码:

//print1.c
#include<stdio.h>
#define NUM 5
int main(int argc,char *argv[])
{for(int i=0;i<NUM;i++){printf("%s\n",argv[1]);fflush(stdout);sleep(1);}return 0;
}
//multi_process.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void){pid_t pid[3];int i;for(int i=0;i<3;i++){pid[i]=fork();if(pid[i]==0){break;//防止子进程再次创建子进程}}if(pid[0]==0){execl("print1","print","Good",NULL);    }else{if(pid[1]==0){execl("print1","print","Hello",NULL);       }else{if(pid[2]==0) execl("print1","print","201919044217",NULL);wait();wait();wait();//调用一次,只能回收一个子进程exit(0);}}return 0;
}

编译过程:#gcc print1.c –o print1
#gcc multi_process.c –o multi
运行截图如下:

time命令

time命令
linux下time命令可以获取到一个程序的执行时间,包括程序的实际运行时间(real time),以及程序运行在用户态的时间(user time)和内核态的时间(sys time)。命令行执行结束时在标准输出中打印执行该命令行的时间统计结果,其统计结果包含以下数据:
1)实际时间(real time): 从command命令行开始执行到运行终止的消逝时间;
2)用户CPU时间(user CPU time): 命令执行完成花费的用户CPU时间,即命令在用户态中执行时间总和;
3)系统CPU时间(system CPU time): 命令执行完成花费的系统CPU时间,即命令在核心态中执行时间总和。
其中,用户CPU时间和系统CPU时间之和为CPU时间,即命令占用CPU执行的时间总和。实际时间要大于CPU时间,因为Linux是多任务操作系统,往往在执行一条命令时,系统还要处理其它任务。
用法:#time ./example

实验结果分析

多进程实验中因为是三个进程并发执行,所以时间上几乎是单个进程的1/3;因为是并发执行的,所以打印结果无序。

四、总结分析

通过两天的学习了解,从Linux系统虚拟机环境搭建,到vim编辑保存文本文件(其实我用的文本编辑器),到用gcc编译.c文件,运行查看结果这一套流程,更加深刻了解了Linux系统下进程控制方式,以及多进程并发执行效果。

操作系统实验:Linux下的进程控制实验相关推荐

  1. Linux第二次试验:Linux下的进程通信实验

    Linux第二次试验:Linux下的进程通信实验 前言 一.实验目的 二.实验工具与设备 三.实验预备知识 三.实验内容和步骤 五.实验代码及步骤截图 六.实验总结 前言 为了帮助同学们完成痛苦的实验 ...

  2. Linux下 prctl 进程控制

    Linux 下 prctl 进程控制 Linux下可通过 prctl进行进程各种控制 #include <sys/prctl.h>int prctl(int option, unsigne ...

  3. Linux下的进程控制原语【pid_t,fork,exec,wait,waitpid,getpid,kill,pasue,sleep,signal】

    目录 一.pid_t 进程号类型 二.与进程创建.执行有关的系统调用说明 fork()系统调用: exec 系统调用: wait() 和 waitpid() 系统调用: getpid()系统调用语法: ...

  4. EDA实验课课程笔记(一)——linux操作系统及linux下的基本指令

    EDA实验课课程笔记(一)--linux操作系统及linux下的基本指令 实验目标 1,了解Linux系统的基本特点 2,掌握Linux的常用命令 3,掌握Linux的命令输入技巧 实验内容 1,基本 ...

  5. 实验四 linux进程控制实验报告,Linux系统进程控制操作系统实验报告4

    实验课程名称:操作系统 实验项目名称Linux系统进程控制实验成绩 实验者专业班级组别 同组者实验日期年月日第一部分:实验分析与设计(可加页) 实验内容描述(问题域描述) 要求:掌握Linux系统中进 ...

  6. linux系统进程控制实验报告,Linux进程控制实验报告.doc

    里奴性进程控制实验报告 实验名称: Linux进程控制 实验要求:一.编写一个Linux系统C程序,由父亲创建2个子进程,再由子进程各自从控制台接收一串字符串,保存在各自的全局字符串变量中,然后正常结 ...

  7. 计算机实验进程管理与虚拟机,虚拟机VMware进程控制实验.docx

    虚拟机VMware进程控制实验 实验6:进程控制操作 1.实验目的 1.了解进程的概念: 2.熟悉Linux的前台与后台进程控制操作: 3.掌握利用进程监控工具来维护系统的正常运行: 2.实验内容 1 ...

  8. linux下ftp服务阶段实验(3)

    linux下ftp服务阶段实验(3) 3.  (1)匿名用户的FTP根目录是/ftp,只能下载,下载速度为100Kbps     (2)本地用户hello的FTP根目录为/hello,可以上传下载,家 ...

  9. 操作系统第二次试验:进程控制试验

    操作系统第二次试验:进程控制试验 前言 实验目的 试验环境 实验内容及步骤 1:练习编写以下实例,来分析和理解Linux中进程的状态转换: 2.(选做)在Linux下,分析程序的功能与运行结果,熟悉L ...

最新文章

  1. oracle 回收碎片,Oracle10g中表的碎片空间回收
  2. (已解决)module ‘tensorflow‘ has no attribute ‘app‘
  3. 你真的了解扩展方法吗?
  4. C++ 内存基本构件 placement new
  5. HDU - 4586 数学期望
  6. layui表头样式_layui中table表头样式修改方法
  7. JS权威指南阅读笔记
  8. 华为手表表盘的数字什么意思_知识 手表防水是什么意思?
  9. 解决Ubuntu SSH登录时过慢的问题-转
  10. 模拟生命_吸烟致癌?
  11. oracle-merge语法
  12. 【2019杭电多校第七场1011=HDU6656】Kejin Player(期望dp+递推+逆元)
  13. PMP第六版 十五至尊图
  14. 面试必备:消息队列原理和选型(荣耀典藏版)
  15. html个人所得税计算器,上海个人所得税计算器_个税计算器_税后工资计算器
  16. 如何实现网页中按钮的自动点击?
  17. XOM版本1.2.5
  18. LeCo-121. 买卖股票的最佳时机
  19. iOS 集成苹果登录及苹果图标的制作要求
  20. Python学习(九)Python缩进规则

热门文章

  1. 计算机管理员账号被禁用了怎么办,Windows 8、Windows 8.1账户没有了管理员权限或唯一的管理员账户被禁用了,怎么办!...
  2. 微信小程序setData 赋值对象属性
  3. java 查看堆外内存占用_Java堆外内存排查小结
  4. jvm堆外内存--DirectByteBuffer
  5. 工业镜头光圈f/#如何影响景深
  6. ON1 Effects 2018 for Mac 12.1.1 照片滤镜 摄影特效 破解版下载
  7. 【AD封装】micro USB座子,Type C座子,USB-A公头
  8. Echarts的使用总结
  9. 计算机图形学(七)——Phong光照模型
  10. [置顶] Fedora使用入门与基本配置