【Linux进行时】进程概念

news/2024/11/23 13:11:54/

在这里插入图片描述

进程的概念

什么是进程呢?

❓首先我们需要认识一下什么叫进程呢?

image-20230811183505468

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

上图我们发现进程是一个个可执行程序!

所有,我们以前的任何启动并运行程序的行为——由操作系统帮助我们将程序转换为进程——完成特定的任务

可执行程序(.exe)本质就是一个普通的二进制文件

❓文件是什么呢? 💡文件等于内容+属性

image-20230418164722723

这个一个个可执行程序(进程)就像我们学生在学校中被管理一样

❓当可执行程序有很多个,都加载到进程里面,那当有成百上千的可执行程序加载到进程,那操作系统会管吗?

❓会管,所以操作系统如何管理进程?

🔥在计算机中,在操作系统内核 里面,要为每个进程加载到内存的时候,操作系统会帮我们创建一个数据结构对象,这个东西在操作系统教材叫pcb,在Linux中叫task_struct

image-20230418165839540

这个结构体提取了所有进程的属性

🔥这里的结构体一个个都是独立,因此可以有结构体指针,可以让pcb直接关联起来,就像链表一样

操作系统,要将其中一个进程结束,将其释放它的代码和数据,和task_struct

❓如果想要执行一个优先级最高的要怎么做呢?

🔥因为pcb是用链表的形式,因此我们可以通过pcb的链表找到优先级最高的地方,然后通过pcb找到进程的代码和数据,将这个进程加载到CPU

现在我们新增加一个进程到内存,然后操作系统要管理进程,因此给你创建了一个pcb,因此对进程的管理就变成了对pcb的管理image-20230418171046084

🔥一般pcb和代码和数据加起来才可以被叫做进程image-20230418171529764

🔥什么是进程:进程=内核关于进程的相关数据结构+当前进程的代码和数据

❓为什么进程管理中需要pcb?

因为我们要管理进程,pcb就是一个struct结构体

image-20230419200616072

Makefile

myprocess:myprocess.cgcc -o myprocess myprocess.c
.PHONY:clean
clean:rm -f myprocess.c

myprocess.c

#include<stdio.h>
#include<unistd.h>
int main()
{while(1){printf("hello process\n");sleep(1);}return 0;
}

image-20230419202454022

这个./就是将可执行程序加载到内存,就做进程,也就是生成了pcb

image-20230419202629638


ps axj指令

🔥ps axj是查看当前所有的进程,通过管道过滤出我的进程

image-20230812095102007

🔥head -1是把对应的第一个TST界面的输出结果的第一行拿到

image-20230419212528377

🔥拿到属性名

image-20230419212629444

这里的逻辑与是先做完前面的,再做后面的

image-20230419212755100

❓这里这个是什么东西啊?grep自己也就一个进程,如果我们只想看到我们自己的进程,不想看到grep进程呢?

image-20230419213001386

我们这里再开一次渠道,也执行可执行程序

image-20230419213202993

查询/proc

一个进程运行起来都有一个对应的一个PID,除了我们用一些指令查看已经运行的进程以外,我们还可以再系统根目录下的proc目录

image-20230419213710924

proc跟普通文件不一样,他是内存级的文件系统,只有当操作系统的启动才有,我们平常的时候没有

image-20230419214003601

这里很明显,这里用数字命名的都是目录,都是d开头的,特定进程的PID

❓特定进程的pid又是什么呢

image-20230419214249620

🔥我们的进程创建后了后,我们的操作系统会自动的在/proc目录下以我们新增的进程的pid命名的

如果我们的进程删掉了呢?,也就是中止进程

image-20230419214633401

我们会发现我们不能查看了,根本原因就是操作系统会自动把那个文件夹删除回收

父子进程

❓如何查询pid?
ps axj | head -1 && ps axj | grep myprocess | grep myprocess | grep -v grep

image-20230419220614197

中止掉后,那个进程就没有了

image-20230419220727077

❓如何我们自己获取一下进程的pid,来证明程序运行起来就是经常呢?

man getpid一下

image-20230419221132903

返回类型是pid_t,这个类型是操作系统的类型就是一个有符号整数

更改一下myprocess.c

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{while(1){printf("hello process,我是一个进程,我的pid是:%d\n",getpid());sleep(1);}return 0;
}

image-20230419222324648

Ctrl+c可以中止进程

man getppid一下

image-20230420212345918

查看父进程pid

🔥我们发现getpid是查询子进程pid,getppid是查看父进程pid

 1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 int main()5 {6   while(1)7   {8     printf("hello process,我是一个进程,我的pid是:%d\n,我的父进程pid为:%d\n",getpid(),getp    pid());9     sleep(1);                                                                              10   }                                                                        11   return 0;                                                                12 }            

image-20230420212940662

❓我们发现就算我们中止一次,虽然我们进程会变,但是我们的父进程基本上不变,这是为什么呢?

我们找一下这个父进程,父进程pid:31059

image-20230420213216078

我们要找的不是与31059相关的,而是就是31059的

ps ajx | head -1 && ps ajx | grep 31059

image-20230420213404837

🔥bash命令行解释器,本质上也是一个进程

❓命令行启动的所有的程序,最终都会变成进程,而该进程对应的父进程都是bash(如何做到的呢?)

❓如果我们不想用Ctrl+c中止,我们可以用什么中止呢?

killed -9 对应的pid

❓如何创建的子进程呢?

man forkz,这个fork后面会详细讲,先用用

🔥fork函数

image-20230420214916223

修改一下myprocess.c

🔥批量注释:Ctrl+v变为视图模式,然后按j向下选中区域,然后按切换为大写模式,按i,然后写//

image-20230420215350949

❓如何批量取消注释

🔥Ctrl+v ,l选中区域,然后d就可以了

 #include<stdio.h>#include<unistd.h>#include<sys/types.h>int main(){printf("AAAAAAAAAAAAAAAAAAAAAAAAA\n");fork();printf("BBBBBBBBBBBBBBBBBBBBBBBBB\n");sleep(1);                                                                                          return 0;
} 

image-20230420220126114

❓这是为什么呢?

image-20230420220413019

🔥谁调pid那就获得谁的pid,说明这是两个进程,这是父子进程,A是第一个进程(也就是第二行那个)

man fork

创建子进程fork

image-20230420221101756

修改一下myprocess.c

#include<stdio.h>#include<unistd.h>
#include<sys/types.h>int main()
{ printf("AAAAAAAAAAAAAAAAAAAAAAAAA:父进程是%d,子进程是%d\n",getppid(),getpid());
id_t ret= fork();printf("BBBBBBBBBBBBBBBBBBBBBBBBB:父进程是%d,子进程是%d,ret=%d,&ret=%p\n",getppid(),getpid      (),ret,&ret);
sleep(1);
return 0;
}

image-20230420222057496

❓为什么fork有两个返回值?

一个是父进程的,一个是子进程的

❓为什么一个变量里面地址一样,读取的数据内容不一样呢?

父子进程是独立的

我们一般不会像上面那样写fork,我们来看一个正常情况下的,

#include<stdio.h>
#include<unistd.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 if(ret>0){while(1){printf("我是父进程,我的pid是%d,我的父进程是:%d\n",getpid(),getppid());sleep(2);}}else{}return 0;
}

image-20230420230158734

❓如何参加子进程呢?

🔥fork就可以

  • fork之后,执行流会变成两个执行流

  • fork之后,谁先运行由调度器决定

  • fork之后,fork之后的代码共享,通常我们通过if和else if来进行执行分流

🔑详细解析:

原理:fork如何看待代码和数据?

进程运行的时候,是具有独立性的,父子进程也是一样

int main()
{pid_t ret=fork();int x=100;if(ret==0){while(1){printf("我是子进程,我的pid是%d,我的父进程是%d,%d,%p\n",getpid(),getppid(),x,&x);sleep(1);}}else if(ret>0){while(1){printf("我是父进程,我的pid是%d,我的父进程是:%d,%d,%p\n",getpid(),getppid(),x,&x);sleep(1);}}else{}return 0;
}

image-20230421161247175

int main()
{pid_t ret=fork();int x=100;if(ret==0){while(1){printf("我是子进程,我的pid是%d,我的父进程是%d,%d,%p\n",getpid(),getppid(),x,&x);sleep(1);}}else if(ret>0){while(1){printf("我是父进程,我的pid是%d,我的父进程是:%d,%d,%p\n",getpid(),getppid(),x,&x);x=4237sleep(1);}}else{}return 0;
}

image-20230421161427623

我们发现父进程的x改了,但是子进程没有!!!

这个情况跟我们刚刚fork返回值不一样的情况一样

image-20230421161710284

写时拷贝,也就是只更改写的时候的情况,不改变读的情况

fork如何理解两个返回值问题

fork调用本质上就是操作系统OS提供的一个函数

在这里插入图片描述


http://www.ppmy.cn/news/1027058.html

相关文章

Redis - 数据类型映射底层结构

简介 从数据类型上体现就是&#xff0c;同一个数据类型&#xff0c;在不同的情况下会使用不同的编码类型&#xff0c;底层所使用的的数据结构也不相同。 字符串对象 字符串对象的编码可以是 int、raw 和 embstr 三者之一。 embstr 编码是专门用于保存简短字符串的一种优化编…

OpenCV实例(八)车牌字符识别技术(一)模式识别

车牌字符识别技术&#xff08;一&#xff09;模式识别 1.模式识别流程2. 模式识别方式 影响并导致汽车牌照内字符出现缺损、污染、模糊等情况的常见因素有照相机的性能、采集车辆图像时光照的差异、汽车牌照的清洁度等。为了提高汽车牌照字符识别的准确率&#xff0c;本节将把英…

Ajax 笔记(一)—— Ajax 入门

笔记目录 1. Ajax 入门1.1 Ajax 概念1.2 axios 使用1.2.1 URL1.2.2 URL 查询参数1.2.3 小案例-查询地区列表1.2.4 常用请求方法和数据提交1.2.5 错误处理 1.3 HTTP 协议1.3.1 请求报文1.3.2 响应报文 1.4 接口文档1.5 案例1.5.1 用户登录&#xff08;主要业务&#xff09;1.5.2…

198、仿真-基于51单片机函数波形发生器调幅度频率波形Proteus仿真(程序+Proteus仿真+原理图+流程图+元器件清单+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、原理图 五、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选…

【C语言】自定义实现strlen函数的3种方法

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C语言中自定义实现strlen函数的3种方法&#xff0c;如果大家觉得我写的不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 在自定义实现strlen函数之前&#xff0c;我们简单的介绍一下strlen函…

数据结构-带头双向循环链表的实现

前言 带头双向循环链表是一种重要的数据结构&#xff0c;它的结构是很完美的&#xff0c;它弥补了单链表的许多不足&#xff0c;让我们一起来了解一下它是如何实现的吧&#xff01; 1.节点的结构 它的节点中存储着数据和两个指针&#xff0c;一个指针_prev用来记录前一个节点…

python函数、运算符等简单介绍2(无顺序)

list&#xff08;列表&#xff09; 列表是Python的一种内置数据类型&#xff0c;列表是可以装各种数据类 型的容器 # 第一种list创建方式 list_name [晓东,小刚,明明,小红,123,123.4,123] print(list_name) print(type(list_name)) # 输出结果&#xff1a; [晓东, 小刚, 明明…

【博客693】alertmanager如何自定义告警template

alertmanager如何自定义告警template 配置alertmanager告警模版 template功能&#xff1a; https://prometheus.io/blog/2016/03/03/custom-alertmanager-templates/ 默认的template&#xff1a; https://github.com/prometheus/alertmanager/blob/main/template/default.tm…