Linux:创建进程 -- fork,到底是什么?

这篇具有很好参考价值的文章主要介绍了Linux:创建进程 -- fork,到底是什么?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 相信大家在初学进程时,对fork函数创建进程一定会有很多的困惑,比如:

  • 1.fork做了什么事情?? 
  • 2.为什么fork函数会有两个返回值?
  • 3.为什么fork的两个返回值,会给父进程谅回子进程pid,给子进程返回0?
  • 4.fork之后:父子进程谁先运行??
  • 5.如何理解同一个变量,会有不同的值??

本篇文章将来仔细回答一下这些问题。

目录

1.如何查看进程

2. 通过系统调用创建进程-fork

2.1 初识fork

2.2 fork原理


1.如何查看进程

1.1 进程的信息可以通过 /proc 系统文件夹查看

通过ls指令来查看所有的进程,proc是动态目录结构,用来存放所有的进程,目录的名称就是用进程的id命名的。

Linux:创建进程 -- fork,到底是什么?,Linux,linux,进程,fork

1.2 进程信息同样可以使用ps(process status)工具来获取

  • 进程id(PID)通过getpid 系统调用获得
  • 父进程id(PPID)通过getppid 系统调用获得
   #include<stdio.h>
   #include<sys/types.h>
   #include<unistd.h>
   int main()
   {
      while(1)
      {
          printf("I am a process! myid:%d parentid:%d\n",getpid(),getppid())    ;
          sleep(1);
      }
      return 0;
  }

 我们可以使用shell再开一个窗口登录一次进行查看。

Linux:创建进程 -- fork,到底是什么?,Linux,linux,进程,fork

"aux" 是 "ps" 命令的选项之一,表示显示所有用户的所有进程,通过查询,可以看到你自己 ./ 启动的进程,最后一个进程是当前的grep的查找进程。

关于当前工作目录

我们在C语言学习文件操作是会提到当前目录,我们以 "w" 方式读取文件时,如果文件不存在,那么文件会在当前工作目录cwd下创建。那么一个进程是如何找到当前目录的呢?

我们让下面代码运行起来

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 int main()
  5 {
  6     //更改当前工作目录
  7     chdir("./wdz");//没有这个目录不会更改,我这里是创建好了这个目录                                                       
  8 
  9     // cwd/hello.txt  
 10     FILE* file = fopen("hello.txt","w");//文件不存在会在当前工作目录下创建
 11     if(file==NULL)
 12     {
 13         return 1;
 14     }
 15     fclose(file);
 16 
 17 
 18     while(1)
 19     {
 20         printf("I am a process! myid:%d parentid:%d\n",getpid(),getppid());
 21         sleep(1);
 22     }
 23     return 0;
 24 }

Linux:创建进程 -- fork,到底是什么?,Linux,linux,进程,fork

  这里通过修改当前目录已经对将文件创建在更改的目录下:

Linux:创建进程 -- fork,到底是什么?,Linux,linux,进程,fork  可以发现:

  • 默认情况下,进程所处的目录就是当前工作目录 
  • 一个进程可以找到自己的可执行程序
  • 每一个进程都有自己的工作目录

2. 通过系统调用创建进程-fork

2.1 初识fork

首先使用fork创建一个进程 

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/types.h>
   
   int main()
   {
       printf("我是一个父进程我的pid:%d\n",getpid());
      
      //创建一个子进程! 
      pid_t id = fork();
      
    //fork之前只有父进程会执行fork之前的代码,fork之后父子进程都要执行后面的代码
  
      while(1)
      {
          printf("我是一个进程,pid:%d,ppid%d,fork return:%d\n",getpid(),getppid(),id);
            //这个printf函数在代码这里只调用一次,但在运行时调用了两次
          sleep(1);//for test
      }
      return 0;
  }

 运行结果:

Linux:创建进程 -- fork,到底是什么?,Linux,linux,进程,fork

看到这里大家的疑惑就出来了

目前可以发现:只有父进程执行fork之前的代码,fork之后,父子进程都要执行后续的代码!

一个函数竟然会有两个返回值???fork成功的时候,会有两个不同的返回值,给子进程返回0;
给父进程返回子进程的pid

fork代码的一般写法:

1.我们为什么要创建子进程?

        我们想让子进程协作父进程完成一些工作,这些工作是单进程解决不了的

2.我们创建子进程是为了让子进程和父进程做一样的事情吗??

        我们创建子进程,就是为了让子进程和父进程做不一样的事情,执行不一样的代码

3. 应该如何保证父子进程做不一样的事情呢?

        可以通过判断fork的返回值,判断谁是父,谁是子,然后让他们执行不同的代码片段!!

使用 if 对父子进程分流:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    printf("我是一个父进程我的pid:%d\n",getpid());
    
    //创建一个子进程! 
    //bash也是用C语言写的,命令行启动的进程,都是bash的子进程,所以bash源代码中创建子进程也是用的fork
    pid_t id = fork();  
    
    //fork()之后,用if进行分流    
    if(id<0) return 1; //进程创建失败                                                                                                          
    else if(id == 0)      
    {                  
        //子进程       
        while(1)       
        {              
            printf("我是子进程,pid:%d,ppid%d,ret:%d,正在执行下载\n",getpid(),getppid(),id); 
            sleep(1);//for test      
        }              
    }                  
    else               
    {                  
        //父进程       
        while(1)       
        {              
            printf("我是父进程,pid:%d,ppid%d,ret:%d,正在执行播放任务\n",getpid(),getppid(),id);   
            sleep(1);//for test    
        }
    }

    return 0;
}

执行结果

Linux:创建进程 -- fork,到底是什么?,Linux,linux,进程,fork

可以发现通过 if 对fork函数返回值进行判断,实现了父子进程可以执行不同的任务。

2.2 fork原理

对于上面的现象,我们来解答一下疑惑

  • 1.fork做了什么事情?? 
  • 2.为什么fork函数会有两个返回值?
  • 3.为什么fork的两个返回值,会给父进程谅回子进程pid,给子进程返回0?
  • 4.fork之后:父子进程谁先运行??
  • 5.如何理解同一个变量,会有不同的值??

1. fork做了什么事情?? 

       用于创建一个进程,在内核中操作系统重新为其申请了一个PCB,并使用父进程的PCB进行初始化,且子进程与父进程同时指向相同的代码。所以fork之前的代码子进程也是可以看到的。

那为什么子进程不从头开始执行呢?

        因为有程序计数器pc,会使代码一句一句执行,子进程在创建时和继承父进程的pc。所以说也会继续向下执行。


2.为什么fork函数会有两个返回值? 

        首先fork是一个函数,如果一个函数return时,说明一个函数的核心工作已经做完。我们知道fork之后代码会共享,所以是fork函数做完核心工作后就会共享,return也会父子进程共享,所以会有两个返回值。


3.为什么fork的两个返回值,会给父进程谅回子进程pid,给子进程返回0?

        因为一个父进程可以有多个子进程,父进程信息中只有pid 和 ppid,为了唯一确定子进程,以后管理和控制子进程,所以返回子进程的pid,而子进程中由于有父进程ppid,所以返回0用来判断进程创建成功没有即可。


4.fork之后:父子进程谁先运行??

        不确定。创建完成子进程,只是一个开始。创建完成子进程之后,系统的其他进程,父进程,和子进程,接下来要被调度执行的,当父子进程的PCB都被创建并在运行队列中排队的时候,哪一个进程的PCB先被选择调度,那个进程就先运行,由操作系统自主决定!!由各自PCB中的调度信息(时间片,优先级等)+调度器算法共同决定。


 5.如何理解同一个变量,会有不同的值??

        进程的独立性,首先是表现在有各自的PCB,进行之间不会互相影响!代码本身是只读的,不会影响!但是数据父子是会修改的,所以代码共享,但是数据各个进程必须想办法各自私有一份!!

这个怎么做到的?通过写时拷贝。这样做的好处就是不用将所有的数据都进行拷贝,当数据需要修改时才做拷贝,可以提高效率。

本篇结束!文章来源地址https://www.toymoban.com/news/detail-753382.html

到了这里,关于Linux:创建进程 -- fork,到底是什么?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [入门篇]Linux操作系统fork子进程的创建以及进程的状态 超超超详解!!!我不允许有人错过!!!

    目录 0.前言 1.fork()创建子进程讲解 1.1fork()的简单介绍 1.2 创建子进程详解 1.2.1 如何理解fork创建子进程 1.2.2 子进程的PCB以及子进程的代码和数据 1.2.3为什么要共享写时拷贝 1.2.4 什么时候发生写时拷贝 1.3 fork函数返回值详解 1.3.1引入fork返回值的作用 1.3.2 fork返回执行逻辑剖析

    2024年03月21日
    浏览(62)
  • 【Linux】进程查看|fork函数|进程状态

    🦄 个人主页—— 🎐 开着拖拉机回家_Linux,大数据运维-CSDN博客 🎐✨🍁 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁🍁🪁🍁🪁 🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁 感谢点赞和关注 ,每天进步一点点!加油! 目录 一、基本概念 1.1 概念提出 1.2 特征 二、描述进程-PCB 2.1 什么是进程

    2024年02月04日
    浏览(42)
  • Linux------进程的fork()详解

    目录 前言 一、fork()的使用 二、fork()的返回值 我们为什么要创建子进程? 父进程与子进程的分流 三、fork的一些难理解的问题 1.fork干了什么事情? 2.fork为什么会有两个返回值  3.fork的两个返回值,为什么会给父进程返回子进程pid,给子进程返回0? 4.fork之后,父子进程谁先

    2024年01月18日
    浏览(37)
  • Linux中的进程、fork、进程状态、环境变量

            进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct 在Linux中描述进程的结构体叫做task_struct。task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包

    2024年02月10日
    浏览(43)
  • Linux--进程--vfork与fork区别

    vfork: 所需头文件: #include sys/types.h #include unistd.h pid_t vfork(void); 功能: vfork() 函数和 fork() 函数一样都是在已有的进程中创建一个新的进程,但它们创建的子进程是有区别的。 参数: 无 返回值: 成功:子进程中返回 0,父进程中返回子进程 ID。pid_t,为无符号整型。 失败:

    2024年02月10日
    浏览(33)
  • 【Linux】进程与可执行程序的关系&&fork创建子进程&&写实拷贝的理解

            系统会将此时在系统运行的进程的各种属性都以文件的形式给你保存在系统的proc目录下。 运行一个程序的时候,本质就是把磁盘中的程序拷贝到内存中,当一个进程运行起来的时候,它本质已经和磁盘中的可执行程序没有直接关系了。   当前我的myprocess程序正在运

    2024年03月19日
    浏览(36)
  • Linux网络编程:socket & fork()多进程 实现clients/server通信

    UNIX网络编程:socket实现client/server通信 随笔简单介绍了TCP Server服务单客户端的socket通信,但是并未涉及多客户端通信。 对于网络编程肯定涉及到多客户端通信和并发编程 (指在同时有大量的客户链接到同一服务器),故本随笔补充这部分知识。 而且并发并发编程涉及到多进程

    2024年02月05日
    浏览(44)
  • 【Linux】进程概念与fork初识——if与else竟然能够同时执行?!

    🌸作者简介: 花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。 🌸 专栏简介:本文收录于 Linux从入门到精通 ,本专栏主要内容为本专栏主要内容为Linux的系统性学习,专为小白打造的文章专栏。

    2024年02月01日
    浏览(34)
  • 《Linux操作系统编程》 第六章 Linux中的进程监控: fork函数的使用,以及父子进程间的关系,掌握exec系列函数

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月11日
    浏览(34)
  • 2.【Linux】(进程的状态||深入理解fork||底层剖析||task_struct||进程优先级||并行和并发||详解环境变量)

    Linux把所有进程通过双向链表的方式连接起来组成任务队列,操作系统和cpu通过选择一个task_struct执行其代码来调度进程。 1.运行态:pcb结构体在运行或在运行队列中排队。 2.阻塞态:等待非cpu资源就绪(硬盘,网卡等资源) 3.挂起态:一个进程对应的代码和数据被操作系统因

    2024年01月22日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包