优秀的进程,从创建开始~
目录
前言:
在实验前,需要先了解一些基本知识~
实验所涉及的函数调用:
1、fork函数
功能:创建一个新的子进程。其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码、组代码、环境变量、已打开的文件代码、工作目录和资源限制。
注意:子进程总是从fork之后开始复制父进程的。
系统调用格式: int fork()
如果Fork调用成功,则在父进程会返回新建立的子进程标识符(PID),而在新建立的子进程中则返回0。如果fork失败则直接返回-1。
调用fork()函数需要
包含头文件#include <unistd.h>
2、wait函数
功能:等待子进程运行结束。如果子进程没有完成,父进程一直等待。wait( )将调用进程挂起,直至其子进程因暂停或终止而发来软中断信号为止。如果在wait( )前已有子进程暂停或终止,则调用进程做适当处理后便返回。调用wait()函数需要包含
头文件#include <sys/wait.h>
系统调用格式:int wait(status)
3、exit函数
功能:终止进程的执行。其中,status是返回给父进程的一个整数。为了及时回收进程所占用的资源并减少父进程的干预,UNIX/LINUX利用exit( )来实现进程的自我终止,通常父进程在创建子进程时,应在进程的末尾安排一条exit( )语句,使子进程自我终止。exit(0)表示进程正常终止,exit(1)表示进程运行有错,异常终止。调用exit()函数需要包含
头文件:#include<stdlib.h>
系统调用格式:void exit(status)
—————————————————————
提示:以下是本篇文章正文内容,下面案例可供参考
正文:
[实验目的]:
1、掌握进程的概念,进一步理解进程和程序的区别。
2、认识和了解并发执行的实质。
3、掌握fork()、wait()、exit()函数。
[实验内容]:
一、进程的创建:
在Linux系统,创建C文件的方法,详情请见我的第一篇博文~
进程的创建:编写一段程序,使用系统调用fork( )创建两个子进程,在系统中有一个父进程和两个子进程活动。让每个进程在屏幕上显示一个字符;父进程显示字符“f”,两个子进程分别显示字符“s” 和“d”。多次运行可执行程序,观察记录屏幕上的显示结果,并分析原因。画出进程树的结构图。
代码:
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/wait.h>intmain(){int p1, p2,pid;while((p1=fork())==-1);printf("ok....\n");// 创建成功为止if(p1==0){//如果是子进程putchar('s');printf(" ");printf("i am the child1:%d ",getpid());printf("the return value:%d\n",p1);exit(0);}else{while((p2=fork())==-1);if(p2==0){putchar('d');printf(" ");printf("i am the child2:%d ",getpid());printf("the return value:%d\n",p2);}else{
pid=wait(0);putchar('f');printf(" ");printf("i am the father:%d the return value:%d\n",getpid(),pid);}}}
结果:
yzy@yzy-virtual-machine:~/new$ ./dd.out
ok....
ok....
s i am the child1:2830 the return value:0
d i am the child2:2831 the return value:0
f i am the father:2829 the return value:2830
****分析:如上图,可清晰得出进程间的关系。*
**
由前言可知,父进程会返回新建立的子进程标识符(PID),而在新建立的子进程中则返回0。
**
**** OK出现两次的原因:
**
由前言可知,子进程总是从fork之后开始复制父进程的!!所以在第一个fork 语句后,有两个进程,一个是父进程,另一个是子进程1,去执行OK语句
。**
******进程树:
#mermaid-svg-VJMZehARWzAKHWHS {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-VJMZehARWzAKHWHS .error-icon{fill:#552222;}#mermaid-svg-VJMZehARWzAKHWHS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VJMZehARWzAKHWHS .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-VJMZehARWzAKHWHS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VJMZehARWzAKHWHS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VJMZehARWzAKHWHS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VJMZehARWzAKHWHS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VJMZehARWzAKHWHS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VJMZehARWzAKHWHS .marker.cross{stroke:#333333;}#mermaid-svg-VJMZehARWzAKHWHS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VJMZehARWzAKHWHS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VJMZehARWzAKHWHS .cluster-label text{fill:#333;}#mermaid-svg-VJMZehARWzAKHWHS .cluster-label span{color:#333;}#mermaid-svg-VJMZehARWzAKHWHS .label text,#mermaid-svg-VJMZehARWzAKHWHS span{fill:#333;color:#333;}#mermaid-svg-VJMZehARWzAKHWHS .node rect,#mermaid-svg-VJMZehARWzAKHWHS .node circle,#mermaid-svg-VJMZehARWzAKHWHS .node ellipse,#mermaid-svg-VJMZehARWzAKHWHS .node polygon,#mermaid-svg-VJMZehARWzAKHWHS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VJMZehARWzAKHWHS .node .label{text-align:center;}#mermaid-svg-VJMZehARWzAKHWHS .node.clickable{cursor:pointer;}#mermaid-svg-VJMZehARWzAKHWHS .arrowheadPath{fill:#333333;}#mermaid-svg-VJMZehARWzAKHWHS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VJMZehARWzAKHWHS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VJMZehARWzAKHWHS .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-VJMZehARWzAKHWHS .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-VJMZehARWzAKHWHS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VJMZehARWzAKHWHS .cluster text{fill:#333;}#mermaid-svg-VJMZehARWzAKHWHS .cluster span{color:#333;}#mermaid-svg-VJMZehARWzAKHWHS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VJMZehARWzAKHWHS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
father
child1
child2
二、根据进程树编写程序:
##编写程序创建进程树如图所示,在每个进程中显示当前进程标识符PID号和父进程标识符。
代码:
#include<stdio.h>#include<sys/types.h>#include<sys/wait.h>#include<unistd.h>#include<stdlib.h>intmain(){int pid,pid2,pid3,pid4;
pid=fork();if(pid<0)printf("error occurred!\n");elseif(pid==0)/* 如果是子进程 */{printf("我是子进程b,进程号是%d\n",getpid());int pid1;
pid1 =fork();if(pid1==0){printf("我是子进程b的子进程c,进程号是%d\n",getpid());exit(0);}}else{printf("我是父进程a,进程号是%d\n",getpid());
pid4=fork();if(pid4==0){printf("我是子进程d,进程号是%d\n",getpid());
pid2=fork();if(pid2==0){printf("我是子进程d的子进程e,进程号是%d\n",getpid());}else{
pid3=fork();if(pid3==0){printf("我是子进程d的子进程f,进程号是%d\n",getpid());exit(0);}}}}return0;}
结果:
yzy@yzy-virtual-machine:~/new$ ./c.out
我是父进程a,进程号是3187
我是子进程b,进程号是3188
我是子进程d,进程号是3189
我是子进程b的子进程c,进程号是3190
我是子进程d的子进程e,进程号是3191
我是子进程d的子进程f,进程号是3192
三、根据程序画进程树:
在Linux系统中运行下面的程序,最多可产生多少个进程,试画出进程家族树。
main()
{
fork();
fork();
}
代码:
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/wait.h>intmain(){int m,n,k;
m=fork();printf("hee ");printf("pid:%d ",getpid());printf("the return value:%d\n",m);
n=fork();printf("ha ");printf("pid:%d ",getpid());printf("the return value:%d\n",n);}
结果:
yzy@yzy-virtual-machine:~/new$ ./hh.out
hee pid:3312 the return value:3313
hee pid:3313 the return value:0
ha pid:3312 the return value:3314
ha pid:3313 the return value:3315
ha pid:3314 the return value:0
ha pid:3315 the return value:0
*****进程树:
#mermaid-svg-cexQCTk9xW30AMv3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cexQCTk9xW30AMv3 .error-icon{fill:#552222;}#mermaid-svg-cexQCTk9xW30AMv3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cexQCTk9xW30AMv3 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-cexQCTk9xW30AMv3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cexQCTk9xW30AMv3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cexQCTk9xW30AMv3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cexQCTk9xW30AMv3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cexQCTk9xW30AMv3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cexQCTk9xW30AMv3 .marker.cross{stroke:#333333;}#mermaid-svg-cexQCTk9xW30AMv3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cexQCTk9xW30AMv3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cexQCTk9xW30AMv3 .cluster-label text{fill:#333;}#mermaid-svg-cexQCTk9xW30AMv3 .cluster-label span{color:#333;}#mermaid-svg-cexQCTk9xW30AMv3 .label text,#mermaid-svg-cexQCTk9xW30AMv3 span{fill:#333;color:#333;}#mermaid-svg-cexQCTk9xW30AMv3 .node rect,#mermaid-svg-cexQCTk9xW30AMv3 .node circle,#mermaid-svg-cexQCTk9xW30AMv3 .node ellipse,#mermaid-svg-cexQCTk9xW30AMv3 .node polygon,#mermaid-svg-cexQCTk9xW30AMv3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cexQCTk9xW30AMv3 .node .label{text-align:center;}#mermaid-svg-cexQCTk9xW30AMv3 .node.clickable{cursor:pointer;}#mermaid-svg-cexQCTk9xW30AMv3 .arrowheadPath{fill:#333333;}#mermaid-svg-cexQCTk9xW30AMv3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cexQCTk9xW30AMv3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cexQCTk9xW30AMv3 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-cexQCTk9xW30AMv3 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-cexQCTk9xW30AMv3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cexQCTk9xW30AMv3 .cluster text{fill:#333;}#mermaid-svg-cexQCTk9xW30AMv3 .cluster span{color:#333;}#mermaid-svg-cexQCTk9xW30AMv3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cexQCTk9xW30AMv3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
father:3312
child1:3313
child2:3314
child3:3315
[实验感想]:
(1)系统是怎样创建进程的?
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
(2)当首次调用新创建进程时,其入口在哪里?
fork调用成功后,子进程与父进程并发执行相同的代码。但由于子进程也继承了父进程的程序指针,所以子进程是从fork()后的语句开始执行(也就是新进程调用的入口)。fork()创建成功,返回值对子进程是0,对父进程是子进程的pid(一个正整数)。在调用fork()后,父进程和子进程均从下一条语句开始执行。另外fork在子进程和父进程中的返回值是不同的。在父进程中返回子进程的PID,而在子进程中返回0。所以可以在程序中检查PID的值,使父进程和子进程执行不同的分支。
(3)当前运行的程序(主进程)的父进程是什么?
这里调用fork创建新进程的进程即为父进程,而相对应的为其创建出的进程则为子进程,因而除了进程0以外的进程都只有一个父进程,但一个进程可以有多个子进程。
小白更新系列第二弹!喜欢的朋友可以点个赞哦~
版权归原作者 yzy杨咩咩(◦˙▽˙◦) 所有, 如有侵权,请联系我们删除。