【Linux】进程周边001之进程概念

news2024/11/25 23:01:08

👀樊梓慕:个人主页

 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C++》《Linux》

🌝每一个不曾起舞的日子,都是对生命的辜负


目录

前言

1.基本概念

2.描述进程-PCB

2.1task_struct-Linux中的PCB

2.2task_struct内容分类(成员)

3.查看进程

3.1通过系统目录查看

3.2通过用户级工具ps查看

4.通过系统调用获取进程标识符(PID)

4.1PCB是属于操作系统的还是属于进程的?

 4.2使用getpid和getppid

5.通过系统调用创建进程(fork初识)

5.1fork函数创建子进程

5.2fork的返回值

5.3使用if进行分流


前言

上篇文章我们说学习系统我们要翻越三座大山:进程周边、文件周边以及线程周边。

那今天我们就对第一座大山:进程周边开启攀登之旅💪

本篇文章主要讲解有关进程的基本概念,以及Linux系统下是如何管理进程的,还记得学习管理的六字真言么?没错,对于进程的管理也是先描述,再组织。

之后我们再来学习下如何查看进程以及进程的标识符PID、父进程的标识符PPID。

最后我们初步的认识下fork函数,并利用fork函数实现创建子进程等。

话不多说,直接进入我们今天的学习✍


欢迎大家📂收藏📂以便未来做题时可以快速找到思路,巧妙的方法可以事半功倍。

=========================================================================

GITEE相关代码:🌟fanfei_c的仓库🌟

=========================================================================


1.基本概念

较为官方的说法:

  • 课本概念: 程序的一个执行实例,正在执行的程序等。
  • 内核观点: 担当分配系统资源(CPU时间,内存)的实体。

辅助理解:

对代码进行编译链接产生的文件我们称之为可执行程序(.exe),执行该程序,该程序会被加载到内存中,此时便称之为进程


2.描述进程-PCB

上节课我们学习了管理的概念,并总结为六字真言:先描述,再组织。

那对于操作系统来说,管理进程的方式仍然归结于这六字真言中。

我们也可以将进程描述起来,描述得到的就是进程控制块PCB(process control block)。

PCB就是进程属性的集合(数据结构),里面存储的是进程信息。

管理不是直接管理人,而是管理人的信息;

管理不是直接管理进程,而是管理进程的信息(PCB)。

此时操作系统对进程的管理就转化为对PCB对象的管理。

那对于某个数据结构的管理我们是很熟悉的,假如我们利用链表的方式进行组织,那对于进程的管理说白了就是对链表的增删查改。

换句话说:进程=PCB(内核数据结构)+可执行程序 

未来,所有对进程的控制和操作,都只和进程的PCB有关,和进程的可执行程序没有关系。

如果愿意,你可以把PCB(Node节点)放到任意数据结构中去。


2.1task_struct-Linux中的PCB

task_struct就是在Linux中描述进程的结构体(Linux是C语言编写)。

你可以理解为PCB是操作系统学科抽象的叫法,而在Linux中具体为task_struct。

即task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含进程的信息。


2.2task_struct内容分类(成员)

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

3.查看进程

3.1通过系统目录查看

根目录下的proc目录,/proc下存储着进程信息。

目录名为数字的即为进程信息的目录,每个目录内存储着他们对应的进程信息。

而这些数字对应着该进程的标识符PID。

比如查看标识符PID=1的进程信息:

当我们新建一个普通的进程,并进入该进程所在目录时:

我们可以利用chdir系统调用接口修改工作目录。


3.2通过用户级工具ps查看

实例:ps ajx/ps aux

该命令可以查看所有系统进程。


现在我们来写一段代码并生成可执行程序,执行后变成进程我们如何查看呢?

(1)代码:

#include<stdio.h>
#include<unistd.h>                                                                                                                  

int main()
{
	while(1)
	{
		printf("I am a process!\n");
		sleep(1);
	}
	return 0;
}

(2)编译后执行:


 (3)打开多窗口方便我们观察


 (4)如何查看单个进程?

首先我们已经知道如何查看系统中所有进程了,即ps ajx,那我们可以利用Linux之前学习的一些指令来显示我们想要查看的单个指令。

实例:ps ajx | head -1 && ps ajx | grep test

对以上指令的解释:


我们来观察一下是否是我们想要的结果:


 我们发现:test进程利用刚才的指令我们得到了该进程的相关信息,但是黄色框内是什么?

其实是grep命令:


 这里也侧面反映出几乎所有独立的指令,就是程序,运行起来也是进程。

这里grep实际也是进程,且该进程内包含有test的信息,所以也显示出来了。

如何去掉这多余信息呢?

实例:ps ajx | head -1 && ps ajx | grep test | grep -v grep

-v选项是反向搜索的意思,即过滤掉包含有grep内容的信息。  


另外我们也可以通过指令对进程进行检测,检测他是否运行:

实例:while :; do ps ajx | head -1 && ps ajx | grep test | grep -v grep; sleep 1;done

观察进程创建和销毁的过程: 


 所以我们发现:进程是有生命的!


4.通过系统调用获取进程标识符(PID)

4.1PCB是属于操作系统的还是属于进程的?

答案是属于操作系统的,虽然PCB记录的是进程的相关信息,但是PCB是由操作系统创建并维护的。

那既然PCB是属于操作系统的,那我们如何查看PCB的信息呢?

在操作系统的那篇文章中我们提到过用户想要获取操作系统的信息,需要调用系统接口。

所以获取进程标识符(PID)等PCB的信息我们需要通过系统调用来获得,所以我们来认识下getpid()。

首先我们利用man getpid查看下命令手册:


我们发现getpid是在2号手册中,利用man man我们知道2号手册中记录的就是系统调用接口。 


 4.2使用getpid和getppid

(1)编写代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
	pid_t id = getpid();
	while (1)
	{
		printf("I am a process!pid:%d\n", id);
		sleep(1);
	}
	return 0;
}

(2)执行可执行程序并观察


那我们再来学习一下getppid(获取父进程的进程标识符)。

一般在Linux中,普通进程,都有他的父进程。

每一个子进程都是由父进程创建出来的。 

子进程只能有一个父进程,父进程可以有多个子进程。

每次执行可执行程序,进程标识符会改变(因为每次都是新的进程)。 

那我们来观察一下他的父进程:

(3)编写代码:

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

(4)执行可执行程序并观察 


我们来查询一下该进程的父进程究竟是什么? 

我们发现该进程的父进程是bash(命令行解释器)。

在命令行启动的进程都是bash的子进程。


5.通过系统调用创建进程(fork初识)

./+可执行程序的方式是一种手动创建进程的方式。fork则是通过系统调用创建进程。

5.1fork函数创建子进程

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

int main()
{
	printf("before fork : I am a process,pid:%d,ppid:%d\n", getpid(), getppid());

	fork();

	printf("after fork : I am a process,pid:%d,ppid:%d\n", getpid(), getppid());
	sleep(2);
	return 0;
}

现象:

 确实如我们所料,fork执行后,创建出了一个子进程。

并且我们发现fork后面的语句执行了两次。

也就是说fork之后,代码共享,从一个进程分为两个分支,一为父,一为子。

 那我们如何知道谁是父谁是子呢?

这就要研究一下fork函数的返回值问题了。

5.2fork的返回值

意思是返回给父进程的是子进程的PID,返回给子进程的是0.

为什么?

  • 因为父:子= 1:n,子找父是很容易的,而父找子必须有子的pid。

两个返回值么?

我们来验证一下:

执行结果: 

也就是说父进程使用该变量就返回子进程的pid,子进程使用就返回0。


提问:fork函数为什么会返回两次? 

当一个函数运行到了最后执行return的时候,这个函数的核心逻辑已经执行完成了!

而fork函数中必然会有创建子进程这一操作,所以在fork函数返回值之前,子进程已经存在了。

所以fork函数会返回两次值写入到变量中。


提问:id怎么可能同一个变量既等于0又等于pid? 

一个进程崩溃会不会影响其他进程呢?答案是不会。

注:任意进程之间是具有独立性的,互相不能影响,即便是父子进程。

子进程被创建时,会继承大部分父进程的属性,即子进程的创建是以父进程为模板的。

模拟场景:父进程或子进程对一共享数据进行修改会发生什么?

前面我们刚说到任意进程之间具有独立性,互相不能影响,所以操作系统必须保证这一点。

假如为子进程修改该数据:子进程会从父进程那拷贝一份到自己这里进行修改,这一行为称之为写时拷贝

父进程修改该数据也如此。

id就是这一共享数据,返回的本质就是写入。

  • linux中可以使用同一变量名,表示不同的内存。

提问:我们创建子进程的目的是什么?

一般而言:我们想让父子做不同的工作。

所以我们就可以利用返回值的不同使用if进行分流


5.3使用if进行分流

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
	int ret = fork();
	if (ret < 0) {
		perror("fork");
		return 1;
	}
	else if (ret == 0) { 
        //child的工作代码段
	}
	else { 
		//father的工作代码段
	}
	sleep(1);
	return 0;
}

本篇内容就到这里,其中有些知识需要学习到进程地址空间才能深入研究,博主会持续更新Linux系列文章,欢迎大家关注哈!

=========================================================================

如果你对该系列文章有兴趣的话,欢迎持续关注博主动态,博主会持续输出优质内容

🍎博主很需要大家的支持,你的支持是我创作的不竭动力🍎

🌟~ 点赞收藏+关注 ~🌟

=========================================================================

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

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

相关文章

贪心算法及相关题目

贪心算法概念 贪心算法是指&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;算法得到的是在某种意义上的局部最优解 。 贪心算法性质&#xff08;判断是否可以使用贪心算法&#xff09; 1、贪…

【SpringBoot教程】SpringBoot 创建定时任务(配合数据库动态执行)

作者简介&#xff1a;大家好&#xff0c;我是撸代码的羊驼&#xff0c;前阿里巴巴架构师&#xff0c;现某互联网公司CTO 联系v&#xff1a;sulny_ann&#xff08;17362204968&#xff09;&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗…

DDD系列 - 第6讲 仓库Repository及Mybatis、JPA的取舍(一)

目录 一、领域层定义仓库接口1.1 设计聚合1.2 定义仓库Repository接口二 、基础设施层实现仓库接口2.1 设计数据库2.2 集成Mybatis2.3 引入Convetor2.4 实现仓库三、回顾一、领域层定义仓库接口 书接上回,之前通过一个关于拆解、微服务、面向对象的故事,向大家介绍了如何从微…

mysql中的DQL查询

表格为&#xff1a; DQL 基础查询 语法&#xff1a;select 查询列表 from 表名&#xff1a;&#xff08;查询的结果是一个虚拟表格&#xff09; -- 查询指定的列 SELECT NAME,birthday,phone FROM student -- 查询所有的列 * 所有的列&#xff0c; 查询结果是虚拟的表格&am…

【GlobalMapper精品教程】067:基于无人机航拍照片快速创建正射影像图

文章目录 一、加载无人机照片二、创建正射影像三、导出正射影像四、worldImagery比对一、加载无人机照片 打开globalmapper软件,点击打开数据文件。 选择配套实验数据data067.rar中的影像,Ctrl+A全选。 在globalmapper中,可以直接将照片加载为如下样式。 二、创建正射影像 …

深入理解网络中断:原理与应用

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…

[GPT]Andrej Karpathy微软Build大会GPT演讲(下)--该如何使用GPT助手

该如何使用GPT助手--将GPT助手模型应用于问题 现在我要换个方向,让我们看看如何最好地将 GPT 助手模型应用于您的问题。 现在我想在一个具体示例的场景里展示。让我们在这里使用一个具体示例。 假设你正在写一篇文章或一篇博客文章,你打算在最后写这句话。 加州的人口是阿拉…

【参天引擎】华为参天引擎内核架构专栏开始更新了,多主分布式数据库的特点,类oracle RAC国产数据开始出现了

cantian引擎的介绍 ​专栏内容&#xff1a; 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构&#xff0c;以及如何实现多机的数据库节点的多读多写&#xff0c;与传统主备&#xff0c;MPP的区别&#xff0c;技术难点的分析&#xff0c;数据元数据同步&#xff0c;多主节点的…

记录 | ubuntu上安装fzf

在 ubuntu 上采用命令行安装 fzf 的方式行不通 指的是采用下面的方式行不通&#xff1a; sudo apt install fzf # 行不通 sudo snap install fzf --classic # 行不通正确的安装方式是&#xff1a; ● 到 fzf 的 git 仓库&#xff1a;https://github.com/junegunn/fzf/re…

Landsat7_C2_SR数据集(大气校正地表发射率数据集)

Landsat7_C2_SR数据集是经大气校正后的地表反射率数据&#xff0c;属于Collection2的二级数据产品&#xff0c;空间分辨率为30米&#xff0c;基于Landsat生态系统扰动自适应处理系统&#xff08;LEDAPS&#xff09;&#xff08;版本3.4.0&#xff09;生成。水汽、臭氧、大气高度…

【SpringBoot教程】SpringBoot 实现前后端分离的跨域访问(Nginx)

作者简介&#xff1a;大家好&#xff0c;我是撸代码的羊驼&#xff0c;前阿里巴巴架构师&#xff0c;现某互联网公司CTO 联系v&#xff1a;sulny_ann&#xff08;17362204968&#xff09;&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗…

【Linux】进程见通信之匿名管道pipe

1.匿名管道的特点 以下管道的统称仅代表匿名管道。 管道是一个只能单向通信的通信信道。为了实现进程间通信.管道是面向字节流的。仅限于父子通信或者具有血缘关系的进程进行进程见通信。管道自带同步机制&#xff0c;原子性写入。管道的生命周期是随进程的。 2.匿名管道通信…

neuq-acm预备队训练week 8 P8794 [蓝桥杯 2022 国 A] 环境治理

题目描述 输入格式 输出格式 输出一行包含一个整数表示答案。 输入输出样例 解题思路 最短路二分 AC代码 #include<bits/stdc.h> using namespace std; long long temp,n, Q; long long f[105][105],min_f[105][105],cut[105],dis[105][105];//cut为减少多少&#x…

ubuntu20.04在noetic下编译orbslam2

ubuntu20.04在noetic下编译orbslam2 参考链接1&#xff1a;https://blog.csdn.net/qq_58869016/article/details/128660588 参考链接2&#xff1a;https://blog.csdn.net/dong123456789e/article/details/129693837 在noetic下的安装环境 1.库安装 sudo apt-get update sudo …

仿交易猫转转闲鱼链接三合一源码+独立后台生成链接

高仿交易猫转转闲鱼源码 搭建教程:添加网站→上传源码→解压源码→导入数据库→修改数据库路径config/Conn.php 不用设置什么伪静态 不会可以看源码里有教程 下载程序&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3

Pytorch-CNN轴承故障一维信号分类(二)

目录 前言 1 数据集制作与加载 1.1 导入数据 1.2 数据加载&#xff0c;训练数据、测试数据分组&#xff0c;数据分batch 2 CNN-2D分类模型和训练、评估 2.1 定义CNN-2d分类模型 2.2 定义模型参数 2.3 模型结构 2.4 模型训练 2.5 模型评估 3 CNN-1D分类模型和训练、评…

玩转大数据10:深度学习与神经网络在大数据中的应用

目录 1. 引言&#xff1a;深度学习和神经网络在大数据中的重要性和应用场景 2. 深度学习的基本概念和架构 3. Java中的深度学习框架 3.1. Deeplearning4j框架介绍及Java编程模型 3.2. DL4J、Keras和TensorFlow的集成 4. 大数据与深度学习的结合 4.1. 大数据与深度学…

第 5 部分 — LLM中红队的深入分析:数学和实证方法

一、说明 大型语言模型 (LLM) 领域正在迅速发展&#xff0c;需要强大的红队策略来确保其安全性和可靠性。 红队是一种模拟对抗性攻击来识别漏洞的方法&#xff0c;需要对理论基础和实际应用有深入的了解。在这个分析中&#xff0c;我深入研究了复杂的数学模型&#xff0c;并提供…

MOSFET 驱动设计

MOSFET 驱动设计 由于 MOSFET 的栅极 G 和源极 S 以及栅极 G 和漏极 D 之间隔着氧化物&#xff08;即绝缘层&#xff09;&#xff0c;所以 MOSFET 也叫绝缘栅场效应晶体管。常用于控制负载电路的通断&#xff0c;这种就属于功率 MOSFET&#xff0c;专用于驱动大功率负载。 1.…

RCNN 学习

RCNN算法流程 RCNN算法流程可分为4个步骤 一张图像生成1K~2K个候选区域&#xff08;使用Selective Search方法&#xff09;对每个候选区域&#xff0c;使用深度网络图特征特征送入每一类的SVM分类器&#xff0c;判别是否属于该类使用回归期器细修正候选框位置 1.候选区域的生…