实验一 进程控制
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 谢谢!