实验一:熟悉Linux基础命令及进程管理
-
实验目的
-
了解linux虚拟机的用途及 基本使用步骤
-
了解进程调度的目的及应用场景
-
加深对进程概念的理解,明确进程和程序的区别。
-
分析进程争用资源的现象,学习解决进程互斥的方法。
-
实验内容
-
使用文件相关的linux的基础命令
-
运行进程处理的代码段,并解释结果
-
对于给定的进程处理问题,可以自行设计解决方案并代码实现
-
-
代码及运行结果分析
1.linux基础文件命令使用
-
创建目录/文件夹:mkdri 目录名
-
文件重命名或移动位置:mv
移动
重命名
-
删除文件或目录 rm ,rm -rf
文件
目录
-
查看文件的全部内容: cat 文件路径
-
查看文件内容:more 文件路径
-
查看文件开头的n行数据: head -n 数字
-
显示文件尾部的n行数据 tail -n 数字
-
复制文件命令cp ,cp -rf
-
在目录下查找,搜索文件:find
2.进程管理
-
代码修正及结果分析
代码1
/*test1*/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> int main() {int i,j,id; if (i=fork()) { j=wait(0); id=getpid(); printf("Parent Process!\n"); printf("i=%d,j=%d,id=%d\n",i,j,id); } else { id=getpid(); printf("Child Process!\n"); printf("i=%d,id=%d\n\n",i,id); } }
结果
分析
在i=fork( ) 处创建子进程分支,父进程fork( )返回子进程id,然后进入堵塞队列,等待子进程变成zombie进程。
子进程fork( )返回0,然后等待父进程被堵塞,子进程进入运行队列,知道运行结束变成zombie进程。
进程树
代码2
/*test2*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { int p1,p2; while((p1=fork())==-1); if(p1==0) printf("b.My process ID is %d\n",getpid()); else { while((p2=fork())==-1); if(p2==0) printf("c.My process ID is %d\n",getpid()); else printf("a.My process ID is %d\n",getpid()); } }
结果
分析
a进程在while((p1=fork())==-1)产生子进程b,在while((p2=fork())==-1)产生子进程c
对于子进程b,p1==0,进入第一个分支,运行输出语句。
a进入第二个分支后产生子进程c,对于子进程c,p2==0,进入第二个分支。
a,b,c的运行顺序与运行的调度算法有关。
进程树
代码3
/*test3*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { int m,n,k; m=fork(); printf("PID:%d\t",getpid()); printf("The return value of fork():%d\t\t",m); printf("he\n"); n=fork(); printf("PID:%d\t",getpid()); printf("The return value of fork():%d\t\t",n); printf("ha\n"); k=fork(); printf("PID:%d\t",getpid()); printf("The return value of fork():%d\t\t",k); printf("ho\n"); }
结果
分析
父进程运行,4135进程依次经由m/n/k=fork()产生三个子进程4136,4137,4138
4137进程运行,经由k=fork()产生子进程4139
4136进程运行,经由n/k=fork()产生子进程4140,4141
4139进程运行
4141进程运行
4140进程运行,经由k=fork()产生子进程4142
4142进程运行
进程树
代码4
/*test4*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main(){ int p1,p2,i; FILE *fp; fp = fopen("1.txt", "w+"); while((p1=fork())==-1); if(p1==0) for(i=0;i<50000;i++) fprintf(fp,"son%d\n",i); else { while((p2=fork())==-1); if(p2==0) for(i=0;i<50000;i++) fprintf(fp,"daughter%d\n",i); else for(i=0;i<50000;i++) fprintf(fp,"parent%d\n)",i); } }
结果
分析
Parent进程经由while((p1=fork())==-1),while((p2=fork())==-1)分别产生子进程son,daughter
每个进程经由分支会进入一个长度为50000的循环,循环过程中其运行会被交替打断
进程树
与test1_2相同
-
题目1
代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { int p1,p2,p3; while((p1=fork())==-1); if(p1!=0)printf("fork p1 ,pa:%d ,son:%d\n",getpid(),p1); else printf("b1\'s id is%d\n",getpid()); while((p2=fork())==-1); if(p2!=0){ printf("fork p2 ,pa:%d ,son:%d\n",getpid(),p2); if(p1!=0){ while((p3=fork())==-1); if(p3!=0){ printf("fork p3 ,pa:%d ,son:%d\n",getpid(),p3); printf("a1 id is%d\n",getpid()); } else{ printf("b3 id is%d\n",getpid()); } } } else if(p1!=0)printf("b2\'s id is%d\n",getpid()); else printf("c1\'s id is%d\n",getpid()); }
结果
进程树
-
题目2
代码
/*test4*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main(){ int p1,p2,i; FILE *fp; fp = fopen("1.txt", "w+"); while((p1=fork())==-1); if(p1==0){ lockf(1,1,0); //fprintf(fp,"locking~\n"); for(i=0;i<70000;i++) fprintf(fp,"son%d\n",i); //fprintf(fp,"unlocking~\n"); lockf(1,0,0); } else{ while((p2=fork())==-1); if(p2==0){ lockf(1,1,0); //fprintf(fp,"locking~\n"); for(i=0;i<70000;i++) fprintf(fp,"daughter%d\n",i); //fprintf(fp,"unlocking~\n"); lockf(1,0,0); } else{ lockf(1,1,0); //fprintf(fp,"locking~\n"); for(i=0;i<70000;i++) fprintf(fp,"parent%d\n)",i); //fprintf(fp,"unlocking~\n"); lockf(1,0,0); } } }
结果分析
对于运行结果,在别人的虚拟机上运行可以实现加锁代码段运行时完全被锁,而在我自己的虚拟机上运行时只能是大部分时间的锁定,而非完全锁定,结果如下:
当循环长度为1000时:
可以保证在100%的运行时间段内都不被打断。
当循环长度是10000是:
可以保证在100%的运行时间段内都不被打断。
当循环长度是50000时:
会在运行将近结束的时候被打断,被打断的时间点是固定的,parent进程会在i=49690处被打断,daughter会在i=49944处被打断
接续被打断的时间则是随机的。
当循环长度是100000时:
Parent会在i=99787处被打断,daughter会在i=99974处被打断。
打断和接续情况与之前相同,仍是打断时间固定,接续时间随机。
目前原因尚未得知,推测与io中断处理有关。
通过此次实验,了解并掌握了linux系统虚拟机的基本使用方法。由于linux的内核较为简单且其有大量跨平台的硬件支持,大部分是用C 语言编写的,所以有助于操作系统课程的学习和实践。
在实验中也初步对linux的进程管理产生了了解,但学习尚不深入,仍有许多不甚明了的问题,如:在不同电脑上(vmvare和ubuntu镜像版本相同)程序2中a,b,c进程的运行顺序不同;程序设计问题二中的Lockf处理结果也不同。这些问题留给未来的操作系统学习过程中解决。