【Linux】进程概念与fork初识——if与else竟然能够同时执行?!

news2025/1/19 22:09:38

在这里插入图片描述

文章目录

  • 💐专栏导读
  • 💐文章导读
  • 🌷进程是什么
  • 🌷进程的描述——PCB
  • 🌷进程的组织
  • 🌷如何查看进程
  • 🌷如何通过系统调用查看进程PID
  • 🌷通过系统调用创建进程
    • 🌺认识fork
    • 🌺重点来啦!!!

💐专栏导读

🌸作者简介:花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C语言初阶专栏,本专栏主要内容为本专栏主要内容为Linux的系统性学习,专为小白打造的文章专栏。

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法

💐文章导读

本章我们正式进入进程的学习。本章的主要内容有进程的概念、PCB说明、进程的先描述再组织、如何查看进程、以及学习getpidgetppidfork等系统调用如何使用~

在这里插入图片描述

🌷进程是什么

开门见山一句话——

  • 进程=内核关于进程的相关数据结构+当前代码的内容和数据

🍁如何理解?

当我们写好一段代码进行编译、链接等一系列过程之后,生成了可执行程序。此时的可执行程序是一个文件,被存放到硬盘中。当我们运行该可执行程序后,该程序的代码和数据会被预先加载到内存中(至于原因上一章我们已经做了很好的铺垫),同时操作系统会对该进程建模,提取该进程有关的状态信息等所有的属性并将这些信息保存到一个叫PCB的结构体中,并将该PCB的指针保存到某种例如链表一样的数据结构当中,以进行对进程的增删查改一系列操作。

简单归纳,“程序被加载到内存中就成为了进程”这就话并不准确,关键是该进程相关的信息有没有被操作系统所管理。就如同,诺大的校园中,如何证明你是学校的学生呢?你说你能从学校的大门进到学校里来,这显然不能说明你就是这个学校的学生,而是当学校的档案系统里记录了你的信息,才能证明你是这个学校的学生。

所以,以前我们任何将程序启动并运行的行为本质上是操作系统将该程序转化为进程从而完成特定的任务。

上文中还有一个很中还要的点需要我们来理解——PCB是什么?有什么作用?

🌷进程的描述——PCB

操作系统如何管理进程?还记得上一章中最重要的六个字吗?——先描述,再组织PCB就是对进程的一种描述。

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合
  • 课本上称之为PCB(process control block),Linux操作系统下的PCB是:task_struct

总结为一句话就是——在Linux中描述进程的结构体叫做task_structtask_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息

🍁task_struct包含以下内容:

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程;
  • 状态: 任务状态,退出代码,退出信号等;
  • 优先级: 相对于其他进程的优先级;
  • 程序计数器: 程序中即将被执行的下一条指令的地址;
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针;
  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器;
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表;
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等;
  • 其他信息

🌷进程的组织

所有的进程都会以task_struct结构体的形式被描述起来。而这些task_struct结构体都会被链接起来,生成一个task_struct类型的链表。操作系统对进程的控制就会转化为对task_struct增删查改

🌷如何查看进程

首先我们写一个简单的程序(命名为myprocess),并运行:

#include<stdio.h>

int main()
{
  while(1)
  {
    printf("我是一个进程\n");
    sleep(1);
  }
  return 0;
}
$ gcc myprocess.c -o myprocess
$ ./myprocess

在分屏的情况下,输入指令查看进程:

ps axj | head -1 && ps axj | grep myprocess | grep -v grep

我们暂且不需要管这条指令的具体指令有什么作用,只需要知道它能显示当前myprocess进程的信息。如图所示:

在这里插入图片描述
虽然我们现在可能看不到每个标识符代表什么意思,但是其它先不用管,只需要知道PID是当前进程的ID,就如同我们的学号

🍁第二种方式

还有一种查看进程的方式:

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

让我们再以myprocess为例。

  • 进入/proc目录;
  • ls 查看目录下的文件;

🍁myprocess未运行时

在这里插入图片描述
我们观察到有很多数字命名的文件,其实猜测一下就能大致猜出这些数字应该就是每个进程对应的PID。

  • 运行myprocess

🍁myprocess运行时

在这里插入图片描述

如图所示,该目录下的确有该进程的相关文件。

🌷如何通过系统调用查看进程PID

除了上述以指令的方式输出PID外,我们还可以用系统调用getpid()获取当前进程的pidgetppid()获取当前进程的父进程的PID

首先通过man手册查询这两个函数如何使用:

$ man getpid

在这里插入图片描述
注意,返回值类型未pid_t其实就是size_t。通过一下代码进行测试:

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

int main()
{
  while(1)
  {
    printf("我是一个进程,我的PID是:%d,我的父进程是:%d\n",getpid(),getppid());
    sleep(1);
  }
  return 0;
}

运行结果为:
在这里插入图片描述
当我们尝试不断地启动程序和结束程序:

在这里插入图片描述
我们可以发现一个规律:

  • 每次启动时,该进程的PID都不同,但是PPID好像每次都一样。

那么PID是什么呢?为什么会不变呢?当你在命令行中启动任何一个进程,它的父进程的PID都是它,即这些进程都有一个共同的父进程——bash(命令行解释器)。如图所示:

在这里插入图片描述

🌷通过系统调用创建进程

接下来的内容为本章的重点内容——认识fork与如何通过fork创建子进程

🌺认识fork

首先我们通过man手册认识一下fork

$ man fork

在这里插入图片描述
在这里插入图片描述

简单说明就是**fork用来创建子进程,在父进程中,fork的返回值为子进程的PID;在子进程中返回值为0**。

话不多说,我们来进行测试:

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

int main()
{
  printf("我是fork调用之前的内容.....\n");
  fork();
  printf("我是fork调用之后的内容.....\n");

  return 0;
}

在这里插入图片描述
很显然,这里fork调用之后的内容打印了两遍。原因是当调用fork之后,子进程被创建,父进程与子进程同时在运行,于是父进程打印了一遍fork调用后的内容,子进程也打印了一遍fork调用后的内容。

如何证明呢?修改代码,在打印内容的同时打印父子进程各自的PIDPPID

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

int main()
{
  printf("我是fork调用之前的内容.....我的PID是:%d,我的父进程是:%d\n",getpid(),getppid());
  fork();
  printf("我是fork调用之后的内容.....我的PID是:%d,我的父进程是:%d\n",getpid(),getppid());

  return 0;
}

在这里插入图片描述

🌺重点来啦!!!

fork的功能很强大,我们一般需要与if配合使用进行分流。还记得上面提到的fork的返回值吗?子进程返回值为0,父进程返回值为子进程PID,可以此作为分流的依据。例如:

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

int main()
{
  pid_t ret = fork();

  if(ret==0)
  {
    // 子进程
    while(1)
    {
       printf("我是子进程,我的PID是:%d,我的父进程是:%d\n",getpid(),getppid());
       sleep(1);
    }
  }
  else 
  {
    // 父进程
    while(1)
    {
       printf("我是父进程,我的PID是:%d,我的父进程是:%d\n",getpid(),getppid());
       sleep(1);
    }
  }

  return 0;
}

在这里插入图片描述

如图所示,此刻父子进程都在运行。那么问题来了——

  • 请问为什么此时ifelse竟然能够同时执行?也就是fork为什么会有两个返回值
  • 又问为什么此时的ret竟然会同时存在两个不同的值?

以上的问题确实有些颠覆初学者的三观。在本章节我们只能够试着解决第一个问题,至于第二个问题,我们在后续进程地址空间中会解释明白。

首先,我们得清楚一个基本概念:

  • 进程间是互相独立的

例如qq与微信同时运行,两个并无关联,互不影响。

其次我们要明白子进程是如何创建的。

我们知道进程=内核数据结构(PCB)+代码和数据。当子进程创建时,操作系统会为子进程创建一个PCB记录子进程的状态信息等。同时子进程会与父进程共同使用一份代码和数据,若有任意一个执行流(只父子进程)修改数据时,操作系统会为该进程将代码和数据拷贝一份,再进行修改,此动作我们称之为写时拷贝写时拷贝同样为非常重要的知识,但是现在我们只做了解即可。

最后,因为进程具有独立性,同样父子进程也具有独立性,且由于写时拷贝的存在,父进程中调用fork会返回子进程的PID,所以else执行了,这是父进程的行为;子进程中会fork会返回0,所以if执行了,这是子进程的行为。父子进程互不影响。

本章的内容就到这里了。关于fork我们还需要学习很多,本章我们就先简单认识一下即可。

在这里插入图片描述

点击下方个人名片,可添加博主的个人QQ,交流会更方便哦~
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓

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

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

相关文章

TuGraph 开源数据库体验

TuGraph 开源数据库体验 文章目录 TuGraph 开源数据库体验1. 简单介绍2. 可视化界面体验&#xff1a;查询界面&#xff1a;数据建模&#xff1a;数据导入&#xff1a; 3. 体验心得&#xff1a; 1. 简单介绍 TuGraph 是蚂蚁集团自主研发的大规模图计算系统&#xff0c;提供图数…

大数据技术之SparkSQL

第1章 Spark SQL概述 1.1 什么是Spark SQL 1&#xff09;Spark SQL是Spark用于结构化数据&#xff08;Structured Data&#xff09;处理的Spark模块。 1.2 为什么要有Spark SQL 1.3 Spark SQL原理 1.3.1 什么是DataFrame &#xff08;1&#xff09;DataFrame是一种类似RDD的分…

统计学习方法第四章——朴素贝叶斯法

x.1 前言 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。是通过给定training dataset学习联合概率分布的方法&#xff0c;是一种生成方法。 x.2 使用贝叶斯定理做分类 使用贝叶斯定理做分类&#xff0c;相比较于朴素贝叶斯即丢除特征条件独立假设这个条件。 …

MySQL主从复制详细介绍

一、主从复制的目的 ​ MySQL内建的复制功能是构建基于MySQL的大规模、高性能应用的基础&#xff0c;复制功能的目的是构建高性能的应用&#xff0c;同时也是高可用性、可扩展性、灾难恢复、备份以及数据仓库等工作的基础。比较常见的用途有以下几种&#xff1a; 数据分布&am…

APP渗透—查脱壳、反编译、重打包签名

APP渗透—查脱壳、反编译、重打包签名 1. 前言1.1. 其它 2. 安装工具2.1. 下载jadx工具2.1.1. 下载链接2.1.2. 执行文件 2.2. 下载apktool工具2.2.1. 下载链接2.2.2. 测试 2.3. 下载dex2jar工具2.3.1. 下载链接 3. 查壳脱壳3.1. 查壳3.1.1. 探探查壳3.1.2. 棋牌查壳 3.2. 脱壳3…

【MiniGPT-4】手把手教部署

最近MiniGPT4开源了&#xff0c;获得了很多网友好评&#xff0c;在Github上获得了1.6万的star&#xff0c;它相比ChatGPT3.5来说&#xff0c;可以实现图片识别&#xff0c;生成想要的文本效果&#xff0c;理解能力非常强。 论文地址&#xff1a;https://github.com/Vision-CAIR…

【大数据之Hadoop】二十一、MapReduce、HDFS、Yarn配合工作(作业提交全过程)

1-11、26为Yarn&#xff1b;12-17为HDFS写数据流程&#xff1b;18-25、27-31为MapReduce&#xff1b;19-25为Shuffle&#xff1b;32-41为HDFS写数据流程。 &#xff08;0&#xff09;MR程序提交到客户端所在的节点&#xff0c;在集群模式中运行MR程序&#xff0c;当运行到主函…

数学建模第七天:数学建模算法篇之插值及MATLAB实现

目录 一、前言 1、引例 2、拟合定义 3、拟合与插值的关系 二、拟合 1、线性最小二乘法求解 ①思路 ②解法 2、MATLAB对线性最小二乘拟合的实现 ①函数说明 ②求解例题 3、MATLAB实现非线性曲线拟合 ①lsqcurvefit函数 ②代码求解 4、MATLAB实现非线性最小二乘拟…

华为2023暑期笔试(2-2)——最近最少使用(LRU, Least recently used)缓存算法

目录 题目内容解答要求&#xff08;解答要求限制了只能使用LRU&#xff09;输入描述样例思路代码 题目内容 你是一名网络工程师&#xff0c;你正在为一家云计算公司开发一个虚拟机管理系统。你的系统需要为每个虚拟机分配一个唯一的ID&#xff0c;用来标识和通信。为了实现这个…

C++基础demo(C++入门基础案例)

C入门基础案例学习与了解 demo16 计算年份是否为闰年&#xff08;各种运算符结合&#xff09;demo17 打印ASCII码表demo18 求完数demo19 密码验证&#xff08;if……else&#xff09;demo20 图书管理&#xff08;if…else if…else&#xff09;demo21 信号灯&#xff08;和--&a…

python中使用ctypes库调用使用MMDeploy C++ SDK编译得到的dll文件时,出现WinError126的解决方法

之前&#xff0c;通过以下两篇文章&#xff0c;着重介绍了&#xff0c;使用openMMLab开发的MMDeploy库对MMxx系列仓库训练得到的权重pth转换得到的onnx&#xff0c;并分别使用python SDK和C SDK进行调用的详细步骤&#xff1a; 使用MMDeploy&#xff08;预编译包&#xff09;转…

Enterprise:如何在 Elastic 企业搜索引擎中添加对更多语言的支持

作者&#xff1a;Ioana-Alina Tagirta Elastic App Search 中的引擎&#xff08;engines&#xff09;使你能够索引文档并提供开箱即用的可调搜索功能。 默认情况下&#xff0c;引擎支持预定义的语言列表。 如果你的语言不在该列表中&#xff0c;此博客将说明如何添加对其他语言…

RabbitMQ笔记

一、MQ与RabbitMQ概述 1. MQ简述 MQ&#xff08;Message Queue&#xff09;消息队列&#xff0c;是基础数据结构中 “先进先出” 的一种数据结构&#xff0c;也是在消息的传输过程中保存消息的容器&#xff08;中间件&#xff09;&#xff0c;多用于分布式系统之间进行通信。 …

[Pandas] 设置DataFrame的index索引起始值为1

导入数据 import pandas as pddf pd.DataFrame([[liver,E,89,21,24,64],[Arry,C,36,37,37,57],[Ack,A,57,60,18,84],[Eorge,C,93,96,71,78],[Oah,D,65,49,61,86]], columns [name,team,Q1,Q2,Q3,Q4]) df 上述DataFrame中的index索引列默认是从0开始的&#xff0c;那么我们…

【Spark】Spark是什么?能干什么?有什么特点?

一、什么是Spark 官网&#xff1a;http://spark.apache.org Apache Spark™ is a multi-language engine for executing data engineering, data science, and machine learning on single-node machines or clusters. Spark是一种快速、通用、可扩展的大数据分析引擎&#xf…

MATLAB连续LTI系统的时域分析(十)

目录 1、实验目的&#xff1a; 2、实验内容&#xff1a; 1、实验目的&#xff1a; 1&#xff09;掌握利用MATLAB对系统进行时域分析的方法&#xff1b; 2&#xff09;掌握连续时间系统零输入响应的求解方法&#xff1b; 3&#xff09;掌握连续时间系统零状态响应、冲激响应和…

AD9739配置解析与数据输出指南

1 概述 本文用于AD9737芯片的配置使用情况&#xff0c;以及数据输出的格式说明情况&#xff0c;数据速率的计算情况等。 AD9739是ADI公司的一款14BIT&#xff0c;可达2.5GSPS采样率的DAC芯片。 2 AD9739的性能 支持的输入数据速率&#xff1a;1.6GSPS TO 2.5GSPS. industry lea…

基于3D渲染和基于虚拟/增强现实的IIoT原理的数字孪生平台的方案论文阅读笔记

基于3D渲染和基于虚拟/增强现实的IIoT原理的数字孪生平台的方案论文阅读笔记 论文原文链接&#xff1a;https://ieeexplore.ieee.org/abstract/document/9039804 本笔记对部分要点进行了翻译和批注&#xff0c;原文和翻译可参考链接阅读&#xff0c;此处不进行完整翻译。 论文…

【服务网格】Service Mesh 是什么?为我们解决了什么问题?

文章目录 背景一、Service Mesh 介绍Service Mesh的定义Service Mesh 诞生 二、Service Mesh 解决的问题三、Service Mesh 的原理四、Service Mesh具体是怎么实现的&#xff1f;Istio是什么&#xff1f;istio架构和主要功能Istio 1.5.1 性能总结Istio与Kubernetesistio的实战案…

四、MyBatis获取参数值的两种方式(重点)

文章目录 四、MyBatis获取参数值的两种方式&#xff08;重点&#xff09;4.1 单个字面量类型的参数4.2 多个字面量类型的参数4.3 map集合类型的参数4.4 实体类类型的参数4.5 使用Param标识参数 四、MyBatis获取参数值的两种方式&#xff08;重点&#xff09; MyBatis获取参数值…