探索父进程和子进程

文章目录

  • 通过系统调用查看进程PID
    • 父进程、子进程
  • 通过系统调用创建进程-fork初识
  • 为什么fork给父进程返回子进程的PID,给子进程返回0
  • fork函数如何做到返回两个值
  • 一个变量为什么同时会有两个返回值?
  • bash
  • 总结

在这里插入图片描述

通过系统调用查看进程PID

getpid()函数可以获取进程的PID,返回的是进程的PID,返回类型为pid_t

在这里插入图片描述

以一个程序为例:

#include <stdio.h>    
#include <sys/types.h>    
#include <unistd.h>    
int main()    
{    
  while(1)    
  {    
    printf("The PID is: %d\n",getpid());    
    sleep(1);                                                                                                                            
  }    
  return 0;    
}    

运行结果如下:

在这里插入图片描述

一段脚本查看程序执行起来后的进程:

在这里插入图片描述

通过getpid()得到的PID和ps指令获取的进程PID是一致的,都是5258

一个进程属性中,除了有自己的进程PID还有父进程PID,ps指令中查询到的PPID是当前进程的父进程的PID,可以是用函数getppid()获取父进程的PID。

父进程、子进程

在这里插入图片描述
这个父进程PID到底是什么?

使用指令查看一下:ps axj | head -1 ; ps axj | grep 4943

在这里插入图片描述

4943是bash进程的PID,bash是命令解释器,他会将用户输入的指令翻译给操作系统核心处理,指令的本质也是一个可执行程序。
结论:当我们在命令行输入指令去执行的时候,bash会帮助我们创建一个子进程去执行该指令。子进程出问题不会影响到父进程。

通过系统调用创建进程-fork初识

创建进程的方式———fork

之前我们是写一段代码来创建一个可执行程序,从而形成一个进程。

现在通过系统调用创建进程。

先来认识一下fork函数:

在这里插入图片描述

fork函数会以调用该函数的进程作为父进程创建一个子进程
创建成功时,会在父进程中返回子进程的PID,在子进程中返回0;如果失败,在父进程中返回-1,没有子进程创建。

#include <stdio.h>    
#include <sys/types.h>    
#include <unistd.h>    
int main()    
{    
  int ret=fork();                                                   
  printf("before : %d!, after: %d\n", getpid(), ret);    
  sleep(1);    
  return 0;    
}  

执行结果:

在这里插入图片描述
会发现:fork后面的代码执行了两次,在fork之前有一个执行流,fork后面有两个执行流。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
  printf("I am process!!");
  pid_t id=fork();
  if(id>0)
  {
    while(1)
    {
      printf("I am parent process,pid=%d,ppid=%d\n",getpid(),getppid());
      sleep(1);
    }
  }
  else if(id==0)
  {
    while(1)
    {
      printf("I am child process,pid=%d,ppid=%d\n",getpid(),getppid());
      sleep(1);
    }
  }                                                                                                                                      
  else 
  {
    printf("error\n");
  }
  return 0;
}

运行效果:

在这里插入图片描述
通过上述代码以及运行效果,当id>0时,执行父进程,当id==0时,执行子进程。ifelse if同时满足,并且这两个程序都是死循环同时在运行。
也就是说明,这里有两个程序在同时运行,即myprocess.exe进程和myprocess.exe进程创建的子进程,从而实现了fork函数创建子进程后,会从原来的一个执行流变成两个执行流。

为什么fork给父进程返回子进程的PID,给子进程返回0

fork之后的代码父子共享,返回不同的值是为了区分不同的执行流。创建父子进程,是为了让父子进程执行不同的任务。

一个父进程可以创建多个子进程,为了区分这些子进程,fork函数在创建子进程后,会给父进程返回子进程的pid。子进程只需调用getppid()函数即可找到父进程。fork函数创建子进程后,只需要给子进程返回一个0用来标识创建成功即可。

fork函数如何做到返回两个值

进程=PCB+代码和数据。

进程的PCB对象会找到对应的代码和数据,然后CPU去调度这个进程,也就是说找到这个代码和数据去运行。调用fork函数创建子进程,实际上是在操作系统中多了一个进程,一样的,它也需要先创建一个属于自己的PCB对象,子进程的PCB对象大部分都是以父进程的PCB对象为模板创建的,即直接从父进程的PCB对象那拷贝过来的,对某一小部分进行修改。

**为什么说子进程和父进程的代码和数据是共享的?**刚刚谈到,子进程创建了属于自己的PCB对象,但是没有代码和数据,因此它只能使用父进程的代码和数据,也就是说父子进程的代码和数据是共享的。

因此fork函数之后程序执行了两次,本质上是父子进程各执行了一次。

创建子进程是为了执行和父进程不同的任务,但是父子进程共享一套代码,因此我们需要给父子进程加一区分,以便于让他们执行不同的任务。fork函数会在父子进程中返回不同的值,用户只需要判断不同的的返回值即可。

fork是一个系统调用接口,本质上是一个函数,在操作系统内执行。fork函数在执行return语句之前子进程的PCB对象就会被创建出来,CPU可以同时去调度父子进程。因此fork函数中的return语句也是父子进程共享的。

fork有两个返回值本质上是因为父子进程共用一份代码导致的,父进程会执行return返回一个值,子进程也会执行return返回一个值。

一个变量为什么同时会有两个返回值?

在代码中,fork函数的返回值我们用变量id来接收:pid_t id=fork(),为什么id可以同时有两个值?

在任何平台,进程在运行的时候都是具有独立性的。也就是说一个进程退出、失败、崩溃了,都不会影响其他进程。父进程和子进程也是两个进程,也具有独立性,父子进程不能访问同一份数据,数据在代码执行过程中可能会被修改。所以子进程要把父进程的数据单独拷贝一份,这个过程是由操作系统来完成的。

子进程可以把父进程的数据全被拷贝一份,但是大部分数据对于子进程来说可能都是没用的,这就造成了浪费,所以操作系统只是把父进程中数据层面的代码临时拷贝一份给子进程,即子进程创建后,会共享父进程的代码和数据,如果子进程需要修改父进程的一部分数据时,操作系统会制止。也就是说,子进程用多少数据,就会拷贝多少数据,效率大大提高。

变量id接收的值是fork函数返回的值,父进程return一次,子进程return一次,子进程会执行写时拷贝,所以变量会有两个返回值,本质上是有两块空间。

共享代码不会影响独立性,因为代码加载到内存之后是不会发生改变的。

bash

bash作为命令行解释器,本身也是一个进程,我们在bash命令行输入指令的本质上也是一个可执行程序,加载到内存后也是一个进程。因此在bash的源代码实现中一定会调用fork函数接口,创建子进程,bash自己去执行命令行解释,子进程去执行我们输入的指令进程。

总结

  • 运行 man fork 认识fork
  • fork有两个返回值
  • 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/507169.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【面试题】RocketMQ如何处理消息重复的问题呢?

对分布式消息队列来说&#xff0c;同时做到确保一定投递和不重复投递是很难的&#xff0c;就是所谓的“有且仅有一次” 。RocketMQ择了确保一定投递&#xff0c;保证消息不丢失&#xff0c;但有可能造成消息重复。 处理消息重复问题&#xff0c;主要有业务端自己保证&#xff…

【Docker】搭建强大易用的个人博客 - Halo

【Docker】搭建强大易用的个人博客 - Halo 前言 本教程基于绿联的NAS设备DX4600 Pro的docker功能进行搭建&#xff0c;采用Halo MySQL实例作为演示。 简介 Halo [ˈheɪloʊ] 是一个简洁&#xff0c;现代&#xff0c;快速且非常灵活的建站工具&#xff0c;它是由一位中国开…

Web漏洞-深入WAF注入绕过

目录 简要其他测试绕过 方式一:白名单&#xff08;实战中意义不大&#xff09; 方式二:静态资源 方式三: url白名单 方式四:爬虫白名单 #阿里云盾防SQL注入简要分析 #安全狗云盾SQL注入插件脚本编写 在攻防实战中&#xff0c;往往需要掌握一些特性&#xff0c;比如服务…

AI人像超分解决方案解析

在数字化高速发展的今天&#xff0c;企业对于视觉内容的需求日益增长&#xff0c;特别是在人像处理方面&#xff0c;高清、细腻的画面质量已成为行业标配。美摄科技&#xff0c;作为业界领先的AI视觉技术提供商&#xff0c;凭借其强大的研发实力和深厚的行业经验&#xff0c;推…

九州金榜|孩子沉迷手机网络是什么原因?应该怎么办?

随着现在社会的发展进步&#xff0c;手机已经是每个家庭必不可少的物品&#xff0c;现在基本每个人都是人手一部手机&#xff0c;有些人会配置多部手机&#xff0c;很多家长在忙碌一天后&#xff0c;回到家中也是手机不离手&#xff0c;经常坐下就开始玩手机&#xff0c;这种行…

JAVA学习笔记21(访问修饰符)

1.访问修饰符 ​ *基本介绍 ​ java提供四种访问控制修饰符号&#xff0c;用于控制方法和属性(成员变量)的访问权限(范围) 1.公开级别&#xff1a;用public修饰&#xff0c;对外公开 2.受保护级别&#xff1a;用protected修饰&#xff0c;对子类和同一个包中的类公开 3.默…

2024.4.1每日一题

LeetCode 故障键盘 题目链接&#xff1a;2810. 故障键盘 - 力扣&#xff08;LeetCode&#xff09; 题目描述 你的笔记本键盘存在故障&#xff0c;每当你在上面输入字符 i 时&#xff0c;它会反转你所写的字符串。而输入其他字符则可以正常工作。 给你一个下标从 0 开始的字…

4个文案写作神器,高效一键生成原创文案!

4个文案写作神器&#xff0c;高效一键生成原创文案&#xff01;在当今数字化时代&#xff0c;内容创作已成为企业营销的关键环节之一。然而&#xff0c;许多营销人员面临着文案创作的挑战&#xff0c;他们需要快速、高效地生成原创文案来吸引受众。幸运的是&#xff0c;现在有四…

刷题之动态规划-路径问题

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;开始刷动态规划的题目了&#xff0c;要特别注意初始化的时候给什么值。 动态规划5个步骤 状态表示 &#xff1a;dp数组中每一个下标对应值的含义是什么->dp[i]表示什么状态转移方程&#xff1a; dp[i] 等于什么1 和 2 是…

鹰眼降尘系统的维护成本高吗(已解答)

一、鹰眼降尘系统的维护成本高吗? 鹰眼降尘系统的维护成本会受到多种因素的影响&#xff0c;包括系统的规模、使用频率、设备质量、维护计划等。一般来说&#xff0c;合理的维护可以降低成本并延长系统的使用寿命。 以下是一些影响鹰眼降尘系统维护成本的因素&#xff1a; 设…

Codigger开发者篇:开启全新的开发体验(三)

Codigger&#xff0c;作为一个集开发、运营与使用私人应用于一体的分布式操作系统&#xff0c;以其独特的魅力与优势&#xff0c;为开发者们打开了全新的世界大门&#xff0c;引领他们迈向了一个前所未有的开发体验之旅。在之前的篇章中&#xff0c;我们已经深入探讨了Codigger…

实时监控iOS应用程序运行日志的工具分享

目录 一、设备连接 二、使用克魔助手查看日志 三、过滤我们自己App的日志 &#x1f4dd; 摘要&#xff1a; 本文介绍了如何在iOS iPhone设备上实时查看输出在console控制台的日志。通过克魔助手工具&#xff0c;我们可以连接手机并方便地筛选我们自己App的日志。 &#x1f4…

智慧公厕:改变城市生活的革命性基础设施

在现代城市的高品质生活要求背景下&#xff0c;公共厕所成为了不可或缺的基础设施。然而&#xff0c;传统的公厕在服务质量、管理效率方面存在一定的问题。为了提供更好的公厕服务&#xff0c;智慧公厕应运而生。通过智能化的管理模式&#xff0c;智慧公厕实现了公厕使用与管理…

C++11标准 - 声明(auto,decltype,nullptr)

C11标准 - 声明&#xff08;auto&#xff0c;decltype&#xff0c;nullptr&#xff09; 前言1. auto2. decltype3. nullptr 前言 c11提供了多种简化声明的方式&#xff0c;尤其是在使用模板时。 1. auto 在C98中auto是一个存储类型的说明符&#xff0c;表明变量是局部自动存…

[蓝桥杯 2019 省赛 AB] 完全二叉树的权值

# [蓝桥杯 2019 省 AB] 完全二叉树的权值 ## 题目描述 给定一棵包含 $N$ 个节点的完全二叉树&#xff0c;树上每个节点都有一个权值&#xff0c;按从上到下、从左到右的顺序依次是 $A_1,A_2, \cdots A_N$&#xff0c;如下图所示&#xff1a; 现在小明要把相同深度的节点的权值…

移动硬盘怎么加密?移动硬盘加密软件有哪些?

移动硬盘是我们在工作中最常用的移动存储设备&#xff0c;为了保护数据安全&#xff0c;需要使用专业的移动硬盘加密软件加密保护。那么&#xff0c;移动硬盘加密软件有哪些&#xff1f; ​BitLocker BitLocker是Windows的磁盘加锁功能&#xff0c;可以用于加密保护移动硬盘中…

Devin、OpenDevin

文章目录 关于 DevinCognition 公司Devin 的能力 关于 OpenDevin⭐️ Research Strategy&#x1f6e0; Technology Stack 使用 OpenDevin安装选择一个 Model在命令行运行 关于 Devin Cognition 发布了世界上第一个完全自主的人工智能软件工程师 Devin&#xff0c;在 SWE-bench…

Bert基础(九)--Bert变体之ALBERT

在接下来的几篇&#xff0c;我们将了解BERT的不同变体&#xff0c;包括ALBERT、RoBERTa、ELECTRA和SpanBERT。我们将首先了解ALBERT。ALBERT的英文全称为A Lite version of BERT&#xff0c;意思是BERT模型的精简版。ALBERT模型对BERT的架构做了一些改变&#xff0c;以尽量缩短…

【C++】vector系列力扣刷题日志(136.只出现一次的数字,118.杨辉三角,26.删除有序数组中的重复项,260.只出现一次的数字 |||)

目录 136.只出现一次的数字 118.杨辉三角 26.删除有序数组中的重复项 260.只出现一次的数字 ||| vector的详细介绍及用法这里就不过多赘述了&#xff0c;可以参考上一篇博客&#xff1a;vector的介绍及使用说明 136.只出现一次的数字 题目&#xff1a; 给你一个 非空 整数…

深入理解鸿蒙生命周期:从应用到组件

在开发鸿蒙&#xff08;HarmonyOS&#xff09;应用时&#xff0c;理解生命周期的概念至关重要。生命周期不仅关乎应用的性能优化&#xff0c;还涉及到资源管理和用户体验等多个方面。本文将详细解析鸿蒙操作系统中应用、页面和组件的生命周期&#xff0c;帮助开发者更好地掌握这…