进程的概念

一.进程和程序的理解

首先抛出结论:进程是动态的,暂时存在于内存中,进程是程序的一次执行,而进程总是对应至少一个特定的程序。

程序是静态的,永久的存在于磁盘中

程序是什么呢?程序其实就是存放在我们磁盘上的可执行程序,它静态的,而且是永久存在的。

image-20240705150158608

进程就是磁盘上的程序,加载拷贝到内存上运行起来的,这就是进程。

image-20240705151023097

在windows上打开任务管理器,我们就可以看到操作系统中运行的所有的进程。

image-20240705150530296

这里存在着很多进程,这么多进程,操作系统要不要将这些进程给管理起来呢?答案是肯定的。那又要如何管理呢?这就引出了之前说的冯诺依曼体系结构中的,先描述,再组织

那要怎么将这些进程描述好,组织好呢?首先操作系统是C语言写的,C语言中描述一个物体的很多属性,都是通过结构体struct概括起来的。而描述进程的这个结构体的全部叫做:PCB。

二.进程的PCB

进程的PCB全称叫做进程控制块(process control block),PCB中部分内容如下:

struct xxxx
{
    //id(也就是pid)
    //代码数据地址
    //优先级
    //程序计数器(pc)
    //struct PCB*next
}

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

进程的运作:

在这里插入图片描述

所以说:进程=可执行程序+内核数据结构(PCB)。

在Linux中,进程的PCB具体是struct task_struct{}

其中可执行程序已经被描述成了PCB,然后操作系统需要将PCB给组织起来,使用链表进行链接,于是对于进程的管理就成了对链表的增删改查。

这里的链表又和之前学习的双向头尾链表有点不同。

struct task_struct//PCB
{
    //各种属性
    struct dlist list;
}
struct dlist//链表
{
    struct dlist*prev;
    struct dlist*next;
}

PCB中有一个结构体对象list,然后该结构体中有prev和next指针将操作系统中PCB给组织起来。

image-20240705162447957

这里不要认为进程的PCB只能存在链表中,操作系统中存在许多组织进程PCB的列表,像运行队列,阻塞队列等等。

后续细说。

三.task_struct中的pid和ppid

1.pid

task_struct中有很多属性,也就是很多字段,那它的核心字段有哪些呢?-贯彻整个的学习的过程。

这里我要说到一个核心字段pid(process id),也就是标识该进程的一个数字,表明它是独一无二的一个进程。

这里我们写一个小小的代码来看看进程的pid。

①test.c文件中,写一个死循环的程序。

#include<stdio.h>                                                                                #include<unistd.h>
int main()
{
     while(1)
     {
        printf("这是一个进程\n");
        sleep(1);
     }
 return 0;
 }

②makefile自动化构建代码。

mycode:test.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f mycode     

然后我们使用make创建出可执行程序,然后执行该可执行程序,于是该可执行程序就变成了进程。

image-20240705182716557

这里鼠标右键,点击复制SSH渠道,为了方便我们观察进程的运行和进程的pid的变化。

使用脚本查看该进程的pid:ps ajx | head -1 && ps ajx | grep mycode

image-20240705183213406

该进程我们写的死循环,它就在一直运行起来的,每次我们使用这个这个脚本查看进程,可以看出mycode进程的pid一直没变过,因为该进程一直在运行。而每次使用该脚本,我们都会使用grep这个程序,一瞬间,grep进程就运行起来并马上死亡,于是看到每次grep,它的pid都会发生变化。

在左边进程一直在运行,可以使用ctrl+c,终止该进程,再使用该脚本查看,就发现该进程pid就看不到了。

还可以使用这个命令来杀死进程:kill -9 进程的pid(无脑杀死进程,后续说的僵尸进程没有办法杀死)

image-20240705183936835

2.ppid

这里可以看到除了进程的pid之外,进程还有ppid,而且ppid的值一直没有变过。

解释:进程中除了自己的pid之外,还有父进程的pid,父进程的pid,在子进程来看就是自己的ppid。

那这个父进程到底是谁呢?父进程其实是bash,也就是我们的命令行解释器。

bash是一直不变的,我们在bash下创建的进程,都是bash的子进程。

马上我们使用函数getpid()和getpppid()就验证了。

四.系统调用接口getpid()和getppid()

上述中,我们使用脚本来查看一个进程的pid,每次都这样子来查看进程的pid就很麻烦,于是有两个系统调用接口就可以直接查看进程的pid和ppid,现在我们直接演示。

注意系统调用接口函数在man 2号手册里面查找,而各种库函数都是在man 3号手册中查找的。

image-20240705190657300

修改源代码:

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

image-20240705192328849

这里即验证成功,该进程的ppid和bash进程的pid是对应上的,故而说明,在bash下创建出来的进程都是bash的子进程。

五./proc/pid目录和PCB的关系

linux中有一个目录proc,它存放着所有的进程。

image-20240705200132515

其中proc/pid目录存放着具体某个进程的一些信息。目录的名称就是以该进程的pid命名的。

image-20240705200930739

当我们将进程启动起来,使用ls /proc/pid命令就可以查看该进程的一些信息。

其中cwd就是该进程的当前工作目录,而exe就是可执行程序,还有很多信息。


image-20240705201301015

当ctrl+c终止掉进程之后,再使用查看同样的目录,该目录就不存在了,由此可以看出,/proc目录结构是动态的


当进程运行起来的时候,我们使用命令make clean将可执行程序删除了(也就是在磁盘上删除了该可执行文件),但是进程此时并不受影响,因为进程已经在内存中运行起的。

然后使用命令查看该进程的信息,可以看到该进程是知道自己的可执行程序是被删除了的。

于是得出一个结论:进程是可以找到自己的可执行程序的,靠的就是cwd这个链接文件。

image-20240705201808927


在/proc/pid下我们可以看到具体某个进程的信息,那么它和进程的PCB的关系是什么呢?

/proc/pid 目录下的内容是操作系统向用户展示的关于进程的一部分信息,它与进程控制块(PCB)有一定的关联。

/proc/pid 中的信息可以被看作是从 PCB 中提取出来的、以可读形式呈现给用户的部分关键数据。这些数据反映了进程的某些状态和特征,是 PCB 中部分重要信息的外在表现。

③例如,/proc/pid/status 文件中的一些字段可能与 PCB 中记录的进程状态信息相对应;/proc/pid/maps 可能与 PCB 中关于进程内存布局的信息相关。

然而,/proc/pid 并不能涵盖 PCB 中的所有详细和底层的控制信息,只是提供了一个便于用户观察和了解进程基本情况的接口。

六.Linux中创建进程的两种方式

1.手动的创建进程

上述的所有过程我们都是手动的创建出进程。

除了手动的创建出进程,我们还可以使用代码来创建出进程。

2.使用代码进行创建

使用函数fork()来创建出子进程。(后续细说)

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

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

相关文章

Windows如何查看端口是否占用,并结束端口进程

需求与问题&#xff1a;前后端配置了跨域操作&#xff0c;但是仍然报错&#xff0c;可以考虑端口被两个程序占用&#xff0c;找不到正确端口或者后端接口书写是否规范&#xff0c;特别是利用Python Flask书写时要保证缩进是否正确&#xff01; Windows操作系统中&#xff0c;查…

Matlab中collectPlaneWave函数的应用

查看文档如下&#xff1a; 可以看出最多5个参数&#xff0c;分别是阵列对象&#xff0c;信号幅度&#xff0c;入射角度&#xff0c;信号频率&#xff0c;光速。 在下面的代码中&#xff0c;我们先创建一个3阵元的阵列&#xff0c;位置为&#xff1a;&#xff08;-1,0,0&#x…

代码随想录算法训练Day57|LeetCode200-岛屿数量、LeetCode695-岛屿的最大面积

岛屿数量 题目描述 力扣200-岛屿数量 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此…

设计模式之单例模式(Java)

单例模式实现方式&#xff1a;懒汉式、饿汉式、双重检查、枚举、静态内部类&#xff1b; 懒汉式&#xff1a; /*** 懒汉式单例模式* author: 小手WA凉* create: 2024-07-06*/ public class LazySingleton implements Serializable {private static LazySingleton lazySinglet…

操作系统中的权限说明

什么是权限 权限在操作系统中是一个重要的功能&#xff0c;它允许你控制谁可以读取、写入或执行某个文件。不同的操作系统和文件系统可能有不同的权限模型&#xff0c;但在类Unix系统&#xff08;如Linux和macOS&#xff09;中&#xff0c;文件权限通常由三部分组成&#xff1a…

提升系统稳定性:熔断、降级和限流策略详解

文章目录 前言一、熔断&#xff08;Circuit Breaker&#xff09;二、降级&#xff08;Degradation&#xff09;三、限流&#xff08;Rate Limiting&#xff09;四、应用案例五、小结推荐阅读 前言 随着互联网业务的快速发展&#xff0c;系统稳定性和高可用性成为现代分布式系统…

Spring源码十三:非懒加载单例Bean

上一篇Spring源码十二&#xff1a;事件发布源码跟踪中&#xff0c;我们介绍了Spring中是如何使用观察者设计模式的思想来实现事件驱动开发的&#xff1a;实际上就是将所有监听器注册到广播器中&#xff0c;并通过监听该事件的监听器来处理时间的。结合前面十二篇文章我们将Spri…

电表读数检测数据集VOC+YOLO格式18156张12类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;18156 标注数量(xml文件个数)&#xff1a;18156 标注数量(txt文件个数)&#xff1a;18156 标…

cs224n作业4

NMT结构图&#xff1a;&#xff08;具体结构图&#xff09; LSTM基础知识 nmt_model.py&#xff1a; 参考文章&#xff1a;LSTM输出结构描述 #!/usr/bin/env python3 # -*- coding: utf-8 -*-""" CS224N 2020-21: Homework 4 nmt_model.py: NMT Model Penchen…

【0基础学爬虫】爬虫基础之scrapy的使用

【0基础学爬虫】爬虫基础之scrapy的使用 大数据时代&#xff0c;各行各业对数据采集的需求日益增多&#xff0c;网络爬虫的运用也更为广泛&#xff0c;越来越多的人开始学习网络爬虫这项技术&#xff0c;K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章&#xff0c;为实现从易到…

九浅一深Jemalloc5.3.0 -- ④浅*配置

目前市面上有不少分析Jemalloc老版本的博文&#xff0c;但最新版本5.3.0却少之又少。而且5.3.0的架构与5之前的版本有较大不同&#xff0c;本着“与时俱进”、“由浅入深”的宗旨&#xff0c;我将逐步分析最新release版本Jemalloc5.3.0的实现。 另外&#xff0c;单讲实现代码是…

多功能工具网站

江下科技在线应用-免费PDF转换成Word-word转pdf-无需下载安装 (onlinedo.cn)https://www.onlinedo.cn/

荞面打造的甜蜜魔法:甜甜圈

食家巷荞面甜甜圈是一款具有特色的美食。它以荞面为主要原料&#xff0c;相较于普通面粉&#xff0c;荞面具有更高的营养价值&#xff0c;富含膳食纤维、维生素和矿物质。荞面甜甜圈的口感可能会更加扎实和有嚼劲&#xff0c;同时带着荞面特有的谷物香气。在制作过程中&#xf…

vue侦听器watch()

侦听器watch&#xff08;&#xff09; 侦听器侦听数据变化&#xff0c;我们可以使用watch 选项在每次响应式属性变化时触发一个函数。 <template><h3>侦听器watch</h3><hr> <p>{{nessage}}</p> <button click"exchage">…

缓存-缓存的使用与基本详解

1.缓存使用 为了系统性能的提升&#xff0c;我们一般都会将部分数据放入缓存中&#xff0c;加速访问。而db承担数据落盘工作。 哪些数据适合放入缓存&#xff1f; 即时性、数据一致性要求不高的访问量大且更新频率不高的数据&#xff08;读多&#xff0c;写少&#xff09; …

IDEA安装IDE Eval Reset插件,30天自动续期,无限激活

第一步&#xff1a; 下载idea 注意&#xff1a;版本要是2021.2.2以下 第二步&#xff1a;快捷键CtrlAlts打开设置 第三步&#xff1a;打开下图中蓝色按钮 第四步&#xff1a;点击弹窗的 “” &#xff0c;并输入 plugins.zhile.io 点击 “ok” 第五步&#xff1a;搜索IDE Ea…

Android ViewPostImeInputStage输入事件处理

InputDispatcher向InputChannel使用socket写入输入事件&#xff0c;触发InputEventReceiver调用来接收输入事件。 ViewPostImeInputStage处理view控件的事件 frameworks/base/core/java/android/view/InputEventReceiver.java dispatchInputEvent frameworks/base/core/jav…

对于老百姓而言VR到底能做什么?

VR技术自诞生以来不断发展&#xff0c;已经广泛应用于教育、医疗、工程、军事、航空、航海、影视、娱乐等方面&#xff0c;譬如&#xff0c;大型工程或军事活动VR预演可以大幅度减少人力物力投入&#xff1b;在航空领域&#xff0c;航天飞行员在训练舱中面对屏幕进行各种驾驶操…

硅纪元应用评测 | 弱智吧大战GPT4o和Claude 3.5 Sonnet

"硅纪元AI应用测评"栏目&#xff0c;深入解析和评测最新的人工智能应用&#xff0c;提供专业见解和实用建议。不论您是AI专家还是科技爱好者&#xff0c;都能找到权威、详尽的测评&#xff0c;帮助您在快速发展的AI领域中做出最佳选择。一起探索AI的真实潜力&#xf…

《梦醒蝶飞:释放Excel函数与公式的力量》9.2 FV函数

9.2 FV函数 FV函数是Excel中用于计算投资或贷款在若干期后的未来值的函数。它是一个非常实用的财务函数&#xff0c;能够帮助我们快速计算投资的最终价值或贷款的期末余额。 9.2.1 函数简介 FV函数用于计算基于定期固定支付和固定利率的投资或贷款的未来值。未来值是指在一定…