理论知识
Linux——进程管理
1.实验目的
(1)加深对进程概念的理解,明确进程和程序的区别。
(2)进一步认识并发执行的实质。
(3)分析进程争用资源的现象,学习解决进程互斥的方法。
2.实验预备内容
(1)复习课本关于进程控制和进程同步的内容,加深对进程管理概念的理解。
(2)认真阅读实验材料中进程管理部分,分析多个进程的运行情况。
3.实验内容
(1)运行源码
运行上文进程管理中给出的例子,查看自己运行的结果,并进行分析。
(2)进程的创建
自己编写一段程序,使用系统调用fork()创建子进程,认识进程的并发执行。
(3)进程的同步
自己编写一段程序,利用fork()、wait()等系统调用实现父子进程间的同步。
#include<stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdlib.h>int main(){int p1,p2,i;while((p1=fork())==-1);if(p1==0){lockf(1,1,0);for(i=0;i<50000; i++)printf("son%d\n",i);lockf(1,0,0);}else{while((p2=fork())==-1);if(p2==0){lockf(1,1,0);for(i=0;i<50000;i++)printf("daughter%d\n",i);lockf(1,0,0);}else{lockf(1,1,0);for(i=0;i<50000;i++)printf("parent%d\n",i);lockf(1,0,0);}}return 0;}
附
(四个进程管理的程序)
程序1
#include "stdio.h"main(){int i,j,k;if (i=fork()){j=wait();printf("Parent Process!\n");printf("i=%d,j=%d,k=%d\n",i,j);}else {k=getpid();printf("Child Process!\n");printf("i=%d,k=%d\n\n",i,k);}}
使用fork()的进程是父进程,通过fork()建立的新进程是子进程。
fork()创建成功,返回值对子进程是0,对父进程是子进程的pid(一个正整数)。
在调用fork()后,父进程和子进程均从下一条语句开始执行。
wait()的功能是阻塞父进程,等待子进程完成后使得父进程继续工作。
wait()的返回值是所等待的子进程的进程标识符。
getpid()返回调用进程的进程标识符,则输出子进程的k与父进程的i,j相等。
输出结果可能是:
Child Process!i=0,k=9351Parent Process!i=9351,j=9351
程序2
#include <stdio.h>main(){int p1,p2;long i;char c1;while ((p1=fork())==-1);if (p1==0){c1='B';write(1,&c1,1);for( i=0;i<3000000;i++) ; c1='b';write(1,&c1,1);}else{while ((p2=fork())==-1);if (p2==0){c1='C';write(1,&c1,1);for( i=0;i<3000000;i++) ;c1='c';write(1,&c1,1);}else{c1='A';write(1,&c1,1);for( i=0; i<3000000; i++) ;c1='a';write(1,&c1,1);}}}
用fork()创建两个子进程,程序运行时,系统中有1个父进程和2个子进程活动。
每个进程在屏幕上显示两个字符,父进程显示“A”和“a”。
write(1,&c1,1)的函数原型write(fd,buf,count):从buf所指向的内存中输出count个字符的信息到fd所代表的文件中,fd为文件号,buf为一个地址,此处fd=1,代表的就是显示屏,从地址&c1处输出一个字符到屏幕上,就是显示出c1,在每一个进程代码中间都有循环语句起延时作用,能够看出进程调度的效果。
为何不使用printf,printf经过缓冲,使用后,“A”和“a”会一次显示出来,不会交错显示。
可能的输出结果:AbbCca,AaBbCc,ABCcba等等。
程序3
main(){int m,n,k;m=fork();printf("PID:%d\t",getpid());printf("The return value of fork():%d\t\t",m);printf("hee\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");}
程序3的简化
main(){fork();printf(“hee\n”);fork();printf(“ha\n”);fork();printf(“ho\n”);}
为了便于观察,先打印出调用进程的进程标识符,而后是fork()的返回值。
若是
main(){fork();printf(“hee\n”);}
打印出
hee (父进程)hee (子进程)
请大家上机抄下结果,画出进程树,在每一个进程结点边上画出标识符。
程序4
#include <stdio.h>main(){int i;if (fork()==0){for(i=0;i<10000;i++) printf(".......................\n");}else{if (fork()==0){for( i=0; i<10000; i++)printf("#################\n");}else for (i=0;i<10000;i++)printf("******************\n");}}
程序4中也是3个进程。
程序5
#include<stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdlib.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());}return 0;}
程序6
#include<stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdlib.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");return 0;}
程序7
#include<stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdlib.h>int main(){int p1,p2,i;while((p1=fork())==-1);if(p1==0)for(i=0;i<50000; i++)printf("son%d\n",i);else{while((p2=fork())==-1);if(p2==0)for(i=0;i<50000;i++)printf("daughter%d\n",i);elsefor(i=0;i<50000;i++)printf("parent%d\n",i);}return 0;}
参考文章