[Linux] Linux进程PCB内部信息的深入理解

news2024/9/23 9:33:04

标题:[Linux] Linux进程PCB内部信息的深入理解

个人主页:@水墨不写bug

(图片来自网络)

目录

一.查看进程

二.认识并了解进程的关键信息

I,PID/PPID

 II,exe

III,cwd

 三、fork()创建进程


正文开始: 

一.查看进程

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


proc目录介绍:

        /proc这个目录下的文件数据是内存级别的数据,操作系统启动,操作系统会遍历进程的PCB,最终形成proc目录下的文件数据。

        这些数据不是磁盘级别,而是内存级别的。

        proc是实时更新的,运行一个进程,这个进程的PID就会出现在proc目录中。


        如:要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹。

我们可以使用ls、top、ps等命令查看当前正在运行的进程:

        ls:

命令:ls /proc

        top:

命令:top

        ps:

命令:ps axj

        特别的,对于ps axj命令,我们如果知道进程的文件名,可以通过管道来获取关键名,进行更高效的搜索展示:

比如我们提前运行起来名字为mytest的程序,那么可以使用管道结合grep:
ps axj | grep mytest

二.认识并了解进程的关键信息

I,PID/PPID

        进程id(PID):每一个进程都有自己的独特的标识自己的ID。

        就像人的身份证,学生的学号一样,一个进程创建的时候会有自己的PID。进程的PID是一个大整数,一旦获取,在进程结束之前都是不变的。同一个可执行程序,在不同时间运行,PID不同,并且后面的PID较大。

        父进程id(PPID):相对父辈的进程的PID;


        我们可以通过 头文件<unistd.h> 的 getpid()  和 getppid() 函数来得到进程的PIDPPID:

#include<unistd.h>
#include<sys/types.h>
using namespace std;
   
int main()
{
    while(1)
    {
          
        int i = 1;
        while(i != 1e9)
        {
            ++i;
        }

        cout<<"-----------"<<endl;                                       
        cout<<"my pid:"<<getpid()<<endl;
        cout<<"my ppid:"<<getppid()<<endl;
    }
    return 0;
}

 上面的进程运行起来之后:

        通过分析,当前运行进程的pid=23654,没什么问题。

        为了方便演示进程,我们故意写了一个死循环;如果想要结束这个进程,我们可以采取如下的方式: 

        杀进程:ctrl + C 或者 kill -9 + 进程PID

        当我们杀掉进程后,再次运行起来,发现pid=变大了,没问题。 但是问题是两次运行的ppid是相同的!通过查询我们发现 ppid=23714的进程正是Bash(命令行解释器)

        在命令行中,执行命令/执行程序的,本质是Bash的进程创建子进程,由子进程执行我们的代码。(Bash是Linux下常用的 shell 外壳)


 II,exe

        exe链接到可执行程序的位置

        进程在运行起来时,exe记录了当前这个运行的程序的位置;是当前程序的固有属性,不变的。


III,cwd

        cwd(current work directory)当前工作目录

        cwd记录了当前工作目录是我们进行操作的目录,是可指定的。一般而言,我们的工作目录就是当前所处的目录。

        这也就解释了在C语言阶段时,当我们在源码中使用fopen时,为什么默认创建的文件的位置是当前文件夹因为cwd会存储当前程序运行的目录位置,并自动拼接在我们创建的文件名称之前,于是创建的文件默认是在当前路径。如果想要指定路径,则需要写绝对路径。


 三、fork()创建进程

        父进程的概念:在Linux中, 程序启动之后,新建任何进程的时候,都是由自己的父进程创建的。

        父进程id(PPID):相对父辈的进程的PID;

        父子进程的关系满足树状结构:一个父进程可以有多个子进程;而一个子进程只有唯一的父进程。

fork函数的man手册解释

         

        通过查看man手册,我们发现fork函数的解释是十分费解的。

         想要理解fork()函数,仅仅看解释还不够,需要理解下面这一段代码并解释清楚运行情况才可以:

        当我们运行起来这一个程序,我们会发现这样的现象:

        我们会发现if和else的语句同时被执行了,一般而言这是不可能发生的事情!

        原因在于,在fork创建一个子进程之后,这个进程的执行分支就不再是一个执行分支了,而是两个执行分支。一个分支的id满足if的条件,而另一个分支的id满足else的条件,所以整体上表现出if和else同时被执行的错觉。

        在前面的讲解中,我们知道:

进程  = 内核数据结构 + 代码和数据

         当我们在进程A中创建一个进程a1时,a1可以拥有内核数据结构,但是a1到哪里去加载代码和数据呢?

        于是,进程A创建的子进程a1就加载了进程A的代码和数据,但是两份代码和数据是相互独立的。也就是说,进程A中的全局变量glo = 0,在fork之后,子进程修改glo,修改的是自己的glo,而不是进程A的glo,进程A的glo仍=0;

         fork:fork创建子进程之后,父子进程的代码共享。但是数据各自独自私有一份,数据独立。

 为什么?

        进程具有很强的独立性,多个进程之间,运行时,互不影响。包括父子进程之间。

        (就比如你在VS上写一个代码,编译出的可执行程序运行时出现野指针,崩了,但是VS不会挂。这就是因为VS进程你写的进程是两个进程,进程之间具有很强的独立性

fork总结:

        1.id的返回值,给父进程(pid),子进程(0);

        2.fork会有两个返回值--为什么?

因为子进程加载了父进程的代码和数据,自己单独返回了id给自己的那一份数据赋值。

        3.接收fork的返回值只有一个变量,怎么会有不同的值?

                本质上与2是相同的问题,此外也是为了保持进程之间的独立性。

                怎么做到的?

                        --进程地址空间

        fork之后哪一个进程先运行?

由操作系统的调度器自主决定。


完·~

未经作者同意禁止转载

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

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

相关文章

vue源码分析(九)—— 合并配置

文章目录 前言1.vue cli 创建一个基本的vue2 项目2.将mian.js文件改成如下3. 运行结果及其疑问&#xff1f; 一、使用 new Vue 创建过程的 2 种场景二、margeOption的详细说明1.margeOption的方法地址2.合并策略的具体使用3.defaultStrat 默认策略方法 三&#xff1a;以生命周期…

OpenResty安装及使用

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

调用本地大模型服务出现PermissionDeniedError的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【机器学习】---神经架构搜索(NAS)

这里写目录标题 引言1. 什么是神经架构搜索&#xff08;NAS&#xff09;1.1 为什么需要NAS&#xff1f; 2. NAS的三大组件2.1 搜索空间搜索空间设计的考虑因素&#xff1a; 2.2 搜索策略2.3 性能估计 3. NAS的主要方法3.1 基于强化学习的NAS3.2 基于进化算法的NAS3.3 基于梯度的…

ICM20948 DMP代码详解(38)

接前一篇文章&#xff1a;ICM20948 DMP代码详解&#xff08;37&#xff09; 上一回继续解析inv_icm20948_set_slave_compass_id函数&#xff0c;解析了第3段代码&#xff0c;本回解析接下来的代码。为了便于理解和回顾&#xff0c;再次贴出该函数源码&#xff0c;在EMD-Core\so…

队列+宽搜专题篇

目录 N叉树的层序遍历 二叉树的锯齿形层序遍历 二叉树最大宽度 在每个树行中找最大值 N叉树的层序遍历 题目 思路 使用队列层序遍历来解决这道题&#xff0c;首先判断根节点是否为空&#xff0c;为空则返回空的二维数组&#xff1b;否则&#xff0c;就进行层序遍历&#x…

chapter 12 Bandgap References

chapter 12 Bandgap References 这一章我们介绍电压和电流基准. 首先学习和输入电压无关的偏置和起动问题. 然后介绍和温度有关的基准电压, 考虑offset对输出电压的影响. 最后学习恒定gm偏置和state-of-the-art电压基准. 12.1 General Considerations 一般基准电流有三种形式…

鸿蒙OpenHarmony【轻量系统芯片移植案例】标准系统方案之瑞芯微RK3566移植案例

标准系统方案之瑞芯微RK3566移植案例 本文章是基于瑞芯微RK3566芯片的khdvk_3566b开发板&#xff0c;进行标准系统相关功能的移植&#xff0c;主要包括产品配置添加&#xff0c;内核启动、升级&#xff0c;音频ADM化&#xff0c;Camera&#xff0c;TP&#xff0c;LCD&#xff…

数据集-目标检测系列-摩托车检测数据集 motorcycle >> DataBall

数据集-目标检测系列-摩托车检测数据集 motorcycle >> DataBall 数据集-目标检测系列-摩托车&#xff08;motorcycle&#xff09;检测数据集 数据量&#xff1a;1W 想要进一步了解&#xff0c;请联系 DataBall。 DataBall 助力快速掌握数据集的信息和使用方式&#xf…

AI 智能名片链动 2+1 模式商城小程序中的体验策略

摘要&#xff1a;本文探讨了在 AI 智能名片链动 21 模式商城小程序中&#xff0c;体验策略如何服务于用户体验&#xff0c;以及与产品策略的区别。重点分析了该小程序如何通过关注用户在使用过程中的流畅度、视觉体感等方面&#xff0c;实现“让用户用得爽”的目标&#xff0c;…

MWD天气图像多分类数据集,用于图像分类总共6个类别,多云,下雨,下雪,雾天,正常天气,共60000张图像数据

MWD天气图像多分类数据集&#xff0c;用于图像分类 总共6个类别&#xff0c;多云&#xff0c;下雨&#xff0c;下雪&#xff0c;雾天&#xff0c;正常天气&#xff0c;共60000张图像数据 MWD天气图像多分类数据集 (Multi-Weather Dataset, MWD) 数据集描述 MWD天气图像多分类…

哔哩哔哩自动批量删除抽奖动态解析篇(三)

前面两节已经介绍了如何获取抽奖动态列表和根据动态id_str索引值判断是否开奖了&#xff0c;接下来我们要完成的就是删除已经开奖了的动态 一、删除已经开奖的抽奖动态 老规矩&#xff0c;我们按F12健进入网页源代码&#xff0c;删除一条动态&#xff0c;观察网络接口 这次…

论文阅读 | 可证安全隐写(网络空间安全科学学报 2023)

可证安全隐写&#xff1a;理论、应用与展望 一、什么是可证安全隐写&#xff1f; 对于经验安全的隐写算法&#xff0c;即使其算法设计得相当周密&#xff0c;隐写分析者&#xff08;攻击者&#xff09;在观察了足够数量的载密&#xff08;含有隐写信息的数据&#xff09;和载体…

Redis数据结构之list列表

一.list列表 列表相当于数组或者顺序表 它里面的元素是有序的&#xff0c;也就是可以通过下标进行访问。这里的有序的含义是要根据上下文区分的&#xff0c;有的时候&#xff0c;有序指的是升序/降序&#xff0c;有的时候有序指的是顺序很关键&#xff0c;俩个元素交换后就不…

Spring6梳理10—— 依赖注入之注入数组类型属性

以上笔记来源&#xff1a; 尚硅谷Spring零基础入门到进阶&#xff0c;一套搞定spring6全套视频教程&#xff08;源码级讲解&#xff09;https://www.bilibili.com/video/BV1kR4y1b7Qc 目录 10 依赖注入之注入数组类型属性 10.1 创建Emp实体类&#xff0c;Dept实体类 10.2…

Java 每日一刊(第15期):内部类

文章目录 前言内部类成员内部类&#xff08;Member Inner Class&#xff09;静态内部类&#xff08;Static Nested Class&#xff09;局部内部类&#xff08;Local Inner Class&#xff09;匿名内部类&#xff08;Anonymous Inner Class&#xff09; 内部类的详细对比内部类字节…

浅谈Spring Cloud:Nacos的配置

Nacos&#xff0c;一个更易于构建云原生应用的动态服务发现&#xff0c;配置管理和服务管理平台。所以Nacos是⼀个注册中心组件&#xff0c;但它又不仅仅是注册中心组件。 目录 安装 注册 负载均衡 环境隔离 配置管理 搭建集群 安装 在官网下载好安装包解压后&#xf…

深度学习01-概述

深度学习是机器学习的一个子集。机器学习是实现人工智能的一种途径&#xff0c;而深度学习则是通过多层神经网络模拟人类大脑的方式进行学习和知识提取。 深度学习的关键特点&#xff1a; 1. 自动提取特征&#xff1a;与传统的机器学习方法不同&#xff0c;深度学习不需要手动…

手机在网状态查询接口如何用Java进行调用?

一、什么是手机在网状态查询接口&#xff1f; 手机在网状态查询接口&#xff0c;又叫运营商在网状态查询&#xff0c;手机号在网状态查询&#xff0c;传入手机号码&#xff0c;查询该手机号的在网状态&#xff0c;返回内容有正常使用、停机、在网但不可用、不在网&#xff08;…

【网络】高级IO——epoll版本TCP服务器初阶

目录 前言 一&#xff0c;epoll的三个系统调用接口 1.1.epoll_create函数 1.1.1.epoll_create函数干了什么 1.2. epoll_ctl函数 1.2.1.epoll_ctl函数函数干了什么 1.3.epoll_wait函数 1.3.1.epoll_wait到底干了什么 1.4.epoll的工作过程中内核在干什么 二&#xff0c;…