操作系统第二次实验作业 16281027

实验一 进程控制

1.实验题目:

根据课堂所学内容和基础知识介绍,完成实验题目。

1、打开一个vi进程。通过ps命令以及选择合适的参数,只显示名字为vi的进程。寻找vi进程的父进程,直到init进程为止。记录过程中所有进程的ID和父进程ID。将得到的进程树和由pstree命令的得到的进程树进行比较。
用vi命令创建一个进程。之后使用ps-A命令查看所有进程信息,可以看到vi进程的进程号pid为4686。
在这里插入图片描述
随后使用ps -df|grep 命令寻找vi进程的父进程,直到进程号为1的init进程。
在这里插入图片描述在这里插入图片描述
通过命令行可以看到,搜索父进程的顺序为4686->4590->1457->1439->1027->1。
直接使用pstree -p命令查看进程树,结果如下。
在这里插入图片描述
可以看到,两种命令途径得出的结果是一致的。

2、编写程序,首先使用fork系统调用,创建子进程。在父进程中继续执行空循环操作;在子进程中调用exec打开vi编辑器。然后在另外一个终端中,通过ps –Al命令、ps aux或者top等命令,查看vi进程的运行状态,理解每个参数所表达的意义。选择合适的命令参数,对所有进程按照cpu占用率排序。
代码如下:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
int main() {
pid_t pid = fork();
if (pid == 0){//子进程
int res = execl(“/usr/bin/vi”,”vi”,NULL);
if(res == 1)
perror(“execl”);//打开vi编辑器
exit(0);
}
else if (pid > 0){//父进程 空循环
while(1);
}
return 0;
}

运行结果如下,
在这里插入图片描述

然后打开另一个terminal窗口Ps-AL命令,可以看到vi的进程号为3842.
在这里插入图片描述
使用Ps aux命令,结果如下图,
在这里插入图片描述
上图中,vi每行从左到右的参数依次代表:
USER 进程的用户, zyh-tony
PID 进程的id, 3842
%CPU 进程占用的CPU百分比, 0.0%(小于0.05%)
%MEM 进程占用内存的百分比, 0.3%
VSZ 进程占用的虚拟内存量, 33784KB
RSS 该进程占用的固定内存量,3916KB
TTY 该进程在哪个终端上运行(登陆者的终端位置),若与终端无关,则显示(?),pts/1
START 该进程被触发启动时间,12:18
TIME 该进程实际使用CPU运行的时间,0:00
COMMAND 命令的名称和参数,vi
查看进程按cpu占有率排序的ps命令为:ps auxw --sort=%cpu
在这里插入图片描述
3、使用fork系统调用,创建如下进程树,并使每个进程输出自己的ID和父进程的ID。观察进程的执行顺序和运行状态的变化

代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
	pid_t p1, p2, p3, p4, p5;
	while ((p1 = fork()) == -1);
	if (!p1) {
		while ((p2 = fork()) == -1);
		if (!p2) {
			while ((p4 = fork()) == -1);
			if (!p4) {
				while (1){
					printf("Node p4 is p2's child with pid %d, it's parent pid %d.\n", getpid(), getpid());
//getpid()输出当前进程id,getppid()输出当前进程的父进程的id。
				}
			}
			else{
				while ((p5 = fork()) == -1);
				if (!p5) {
					while (1){
						printf("Node p5 is p2's child with pid %d, it's parent pid %d.\n", getpid(), getppid());
					}
				}
				else { ; }
			}
		while (1) {
			printf("Node p2 is p1's child with pid %d, it's parent pid %d.\n", getpid(), getppid());
		}
	}
		else { 
			while ((p3 = fork()) == -1);
				if (!p3) {
				while (1){
					printf("Node p3 is p1's child with pid %d, it's parent pid %d.\n", getpid(), getppid());
				}
				}
		}
	while (1) {
		printf("Node p1 is a parent with pid %d, it's parent pid %d.\n", getpid(), getppid());
		}
}
	else { ; }
return 0;
}

程序运行结果如下:

在这里插入图片描述
在这里插入图片描述
由执行结果可知,p1进程的pid号为2753;
p2进程的pid号为2754,父进程的pid号为2753,即p1;
p3进程的pid号为2755,父进程的pid号为2753,即p1;
p4的pid号为2756,父进程的pid号为2754,即p2;
p5的pid号为2757,父进程的pid号为2754,即p2;

4、修改上述进程树中的进程,使得所有进程都循环输出自己的ID和父进程的ID。然后终止p2进程(分别采用kill -9 、自己正常退出exit()、段错误退出),观察p1、p3、p4、p5进程的运行状态和其他相关参数有何改变。

初始进程情况如下:
在这里插入图片描述
执行命令kill -9 2104后结果如下:
在这里插入图片描述
可以看到pid=2104的进程处于defunct状态,p4和p5的父进程变为1302,不是原先的p2了,其他参数不变。

p2段代码修改为:

while (1) 
		{
			printf("Node p2 is p1's child with pid %d, it's parent pid %d.\n", getpid(), getppid());
Exit(0);//正常退出
		}

在这里插入图片描述
可以看到,p4、p5进程的父进程转为1302,在进程树上与p1进程是兄弟节点关系,同时p2进程被正常终止。

执行段错误退出后结果如下:
p2段代码修改为:

while (1) 
		{
		printf("Node p2 is p1's child with pid %d, it's parent pid %d.\n", getpid(), getppid());
		 int *p = NULL;
		 *p = 0;//通过访问不存在的内存地址,引发段错误退出
}

在这里插入图片描述
结果同上。

代码见 https://github.com/Bismarck0116/OS-homework-experiment 谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值