探索父进程和子进程

文章目录

  • 通过系统调用查看进程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有两个返回值
  • 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java设计之道:色即是空,空即是色

引子 我们的这个世界上&#xff0c;存在这么一种东西&#xff1a; 第一&#xff1a;它不占据任何3D之体积&#xff0c;即它没有Volume第二&#xff1a;它也不占据任何2D之面积&#xff0c;即它没有Area第三&#xff1a;它也不占据任何1D之长度&#xff0c;即它没有Length 总之…

CentOS7 RPM升级支持BBR TCP/CC的内核版本

列出安装的内核 rpm -qa kernel # yum list installed kernel 删除已安装内核 sudo dnf remove kernel-4.0.4-301.fc22.x86_64 安装内核 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noar…

【二叉树】Leetcode 101. 对称二叉树【简单】

对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 解题思路 判断一棵二叉树是否是轴对称的&#xff0c;可以通过递归方式进行判断。 1、定义一个递归函数isMirr…

SpringSecurity学习总结(三更草堂)

SpringSecurity安全框架的核心功能是认证和授权&#xff1a; 认证&#xff1a;验证当前访问系统的是不是本系统的用户&#xff0c;并且要确认具体是哪个用户。 授权&#xff1a;经过认证后判断当前用户是否具有进行某个操作的权限。 一般来说中大型的项目都是使用SpringSecurit…

vue3组合式函数

vue3的组合式函数的作用是封装和复用响应式状态的函数。只能在setup 标签的script标签汇总或者setup函数中使用。 普通的函数只能调用一次&#xff0c;但是组合式函数接受到响应式参数&#xff0c;当该值发生变化时&#xff0c;也会触发相关函数的重新加载。 如下 定义了一个…

Ubuntu如何配置有线网(只显示VPN和代理时)

Step 1: 将managed的值改为true Step 2&#xff1a; 加入如下的字段&#xff0c; Step 3: reboot

阿里云CentOS7安装MySQL8

创建目录 [rootnode1 ~]# mkdir /usr/local/mysql [rootnode1 ~]# cd /usr/local/mysql/ 下载安装包 到MySQL官网查看需要下载的版本&#xff0c;并获取到下载地址 https://downloads.mysql.com/archives/community/下载 [rootnode1 mysql]# wget https://downloads.mysql…

做现货白银,要直面实时行情走势!

现货白银拥有完善的交易机制&#xff0c;它每天的实时行情走势中充满着交易获利的机会&#xff0c;但不见得每一位投资者都有把握住的能力。在各种资讯都触手可及的今天&#xff0c;投资者可以轻松地获得现与货白银相关的交易技巧&#xff0c;然而交易的智慧&#xff0c;则需要…

【供应海力士H58GG6MK6GX037存储芯片

17566722766 长期供应各进口原装存储芯片&#xff1a; H58GG6MK6GX037 K3UH7H70AM-AGCL K3UHAHA0AM-AGCL H9HKNNNFBMAVAR-NEH K54GG6AYRHX263 K3UH7H70BH-AGCL K3UHAHA0BM-AGCL K3LK3K30EM-BGCN K3LK4K40BM-BGCN K3LK7K70BM-BGCP K3LK4K40CM-BGCP H9JKNNNFB3AECR-…

Redis 的常见问题及解决方案

1、性能问题&#xff1a; 当 Redis 负载过高时&#xff0c;可能会出现性能下降的情况。这可能是由于大量的并发访问、数据量过大或复杂的操作导致的。 解决方案&#xff1a;优化数据结构的使用&#xff0c;避免使用过于复杂的操作。考虑使用分布式 Redis 架构行水平扩展&#x…

Java 随笔记: 面向对象编程(二)

目录 1. 包 2. 访问修饰符 3. 封装 4. getter和setter方法 5. Java Bean 类 6. 继承 7. super 关键字 8. 方法重写 9. 多态 10. 动态绑定机制 11. Object 类 1. 包 在Java中&#xff0c;包&#xff08;package&#xff09;是一种组织代码的机制。它是一种将相关类…

基于java+SpringBoot+Vue的校园台球厅人员与设备管理系统设计与实现

基于javaSpringBootVue的校园台球厅人员与设备管理系统设计与实现 开发语言: Java 数据库: MySQL技术: SpringBoot MyBatis工具: IDEA/Eclipse、Navicat、Maven 系统展示 前台展示 后台展示 系统简介 整体功能包含&#xff1a; 校园台球厅人员与设备管理系统是一个为校园…

简单设计模式讲解

设计模式是在软件开发中经常使用的最佳实践&#xff0c;用于解决在软件设计中经常遇到的问题。它们提供了可重用的设计&#xff0c;使得代码更加灵活、可维护和可扩展。下面我将为你讲解几种常见的设计模式&#xff0c;并提供相应的C#代码示例。 1. 单例模式&#xff08;Single…

【docker】Dockerfile自定义镜像

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;中间件 ⛺️稳中求进&#xff0c;晒太阳 1.Dockerfile自定义镜像 常见的镜像在DockerHub就能找到&#xff0c;但是我们自己写的项目就必须自己构建镜像了。 而要自定义镜像&#xff0c;就…

算法沉淀 —— 深度搜索(dfs)

算法沉淀 —— 深度搜索&#xff08;dfs&#xff09; 一、计算布尔二叉树的值二、求根节点到叶节点数字之和三、二叉树剪枝四、验证二叉搜索树五、二叉搜索树中第K小的元素 一、计算布尔二叉树的值 【题目链接】&#xff1a;2331. 计算布尔二叉树的值 【题目】&#xff1a; …

一款比Typora更简洁优雅的Markdown编辑器神器(完全开源免费)

前言 自从Typora收费以后经常有朋友会问有没有一个好用、简洁、免费的Markdown编辑器推荐的&#xff0c;今天大姚给大家分享一款比Typora更简洁优雅的、完全开源免费&#xff08;MIT License&#xff09;Markdown编辑器神器&#xff1a;MarkText。 MarkText简介 Typora的完美替…

Java EE:多线程 —— 什么是线程,线程与进程的区别

1、线程是什么 一个线程就是一个 “执行流”。每个线程之间都可以按照顺序执行自己的代码&#xff0c;多个线程之间 “同时” 执行着多份代码。 举例说明&#xff1a; 假设一家公司要去银行办业务&#xff0c;既要进行财务转账&#xff0c;又要进行福利发放&#xff0c;还得进…

Collection与数据结构链表与LinkedList(三):链表精选OJ例题(下)

1. 分割链表 OJ链接 class Solution {public ListNode partition(ListNode head, int x) {if(head null){return null;//空链表的情况}ListNode cur head;ListNode formerhead null;ListNode formerend null;ListNode latterhead null;ListNode latterend null;//定义…

[源码] Android 上的一些快捷方式,如通知、快捷方式等

目录 一、通知0. 配置权限1. 测试发送通知代码2. 打开通知设置界面代码3. 前台服务创建常驻通知 二、快捷方式1. 测试添加动态快捷方式代码 三、开发者图块四、桌面小部件 基于jetpack compose 框架的使用代码 一、通知 参见 官方文档 0. 配置权限 <uses-permission andr…

Android仿高德首页三段式滑动

最近发现很多app都使用了三段式滑动&#xff0c;比如说高德的首页和某宝等物流信息都是使用的三段式滑动方式&#xff0c;谷歌其实给了我们很好的2段式滑动&#xff0c;就是BottomSheet&#xff0c;所以这次我也是在这个原理基础上做了一个小小的修改来实现我们今天想要的效果。…