面试必备系列2:操作系统基础:进程的创建

实验二:进程的创建(小白系列第二弹~)🌸🌸🌸

图片说明

🍀前言:

在实验前,需要先了解一些基本知识~🐴

实验所涉及的函数调用🌝:

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>
  int  main()
    { 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语句

*****🌻🌻🌻进程树:



二、根据进程树编写程序:🍁🍁🍁

编写程序创建进程树如图所示,在每个进程中显示当前进程标识符PID号和父进程标识符。

代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

int main(){
        int pid,pid2,pid3,pid4;
        pid=fork();
        if(pid<0)       
                printf("error occurred!\n");
        else if(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);}}
                                                  }}       
        return 0;
}

结果:

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>

int main()
{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

****进程树🤓🌴🌴🌴:


[实验感想]:

(1)系统是怎样创建进程的?🤔
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
(2)当首次调用新创建进程时,其入口在哪里?🤔
fork调用成功后,子进程与父进程并发执行相同的代码。但由于子进程也继承了父进程的程序指针,所以子进程是从fork()后的语句开始执行(也就是新进程调用的入口)。fork()创建成功,返回值对子进程是0,对父进程是子进程的pid(一个正整数)。在调用fork()后,父进程和子进程均从下一条语句开始执行。另外fork在子进程和父进程中的返回值是不同的。在父进程中返回子进程的PID,而在子进程中返回0。所以可以在程序中检查PID的值,使父进程和子进程执行不同的分支。
(3)当前运行的程序(主进程)的父进程是什么?🤔
这里调用fork创建新进程的进程即为父进程,而相对应的为其创建出的进程则为子进程,因而除了进程0以外的进程都只有一个父进程,但一个进程可以有多个子进程。

小白更新系列第二弹!喜欢的朋友可以点个赞哦~😉😘

#笔记##读书笔记##学习路径##Linux#
全部评论
期待再次更新~
3 回复 分享
发布于 2022-04-20 12:26
三连支持
2 回复 分享
发布于 2022-04-20 13:09
咩咩更新好快/加油
2 回复 分享
发布于 2022-04-20 14:26
基础不牢,地动山摇😶
1 回复 分享
发布于 2022-04-20 08:35
太优秀了,支持大佬
点赞 回复 分享
发布于 2022-04-20 17:33

相关推荐

11-01 08:48
门头沟学院 C++
伤心的候选人在吵架:佬你不要的,能不能拿户口本证明过户给我。。球球了
点赞 评论 收藏
分享
评论
7
10
分享
牛客网
牛客企业服务