【Linux】初识进程

news2024/12/24 20:53:12

文章目录

      • 进程控制块的引入
      • 初识进程控制块(PCB - Process Control Block)
        • 什么是PCB
        • Linux下的PCB
      • 初见进程
        • ps指令查看进程
        • kill指令挂掉进程
        • 通过系统调用接口得到进程的ID(进程标识符)
        • 从根目录下的proc文件查看进程
        • 通过fork函数创建子进程

进程控制块的引入

首先,听到进程这个词肯定不模糊,

因为我们常用的Windows系统就有进程管理器,

可以用进程管理器随时挂掉一个进程。

但是,进程和我们常说的程序有什么区别呢?

很多地方都写到,进程狭义的定义就是加载到内存中运行起来的程序

image-20230105213046114

但真的这么简单吗?

程序中的数据会一五一十地照搬到内存中吗?

照搬到内存之后操作系统又是怎么对零散的数据和代码进行处理呢?

我同时运行十几个程序,

这么多零散的代码和数据操作系统又是怎么能精准管理的呢?

这就引入了一个非常重要的概念 —— 进程控制块(PCB - Process Control Block)


初识进程控制块(PCB - Process Control Block)

什么是PCB

为什么要有进程控制块,

很简单,因为操作系统要管理进程,

要管理就要先描述再组织,

进程控制块就是为了描述进程用的

就好比我们用C 语言写一个简单的学生管理系统,

是不是也要声明一个结构体来描述一个学生呢?

Linux是用C语言写的,

所以Linux下的进程控制块就是用C语言声明的结构体,

它就是task_struct

struct task_struct
{
    ///与进程相关的所有属性
}

这样操作系统就给每一份进程分配了一个PCB,

只需要将各个进程的PCB组织在一起,

对进程的管理就变成了对组织PCB的数据结构的管理。

首先先明确一下,一个进程最基本的要有哪些属性呢?

程序的代码和数据要加载到内存中,

要记录这些代码和数据的地址吧;

每个进程要区分一下吧,

要给每个进程编号并记录一下吧;

进程是在等待,还是在运行,还是在挂起,

要记录进程的状态吧;

这个进程是先执行还是后执行,

进程的优先级要记录吧;

进程执行到了哪里,下一条代码该执行什么,

这个也需要记录吧…

各种相关的属性集合在一起,加上程序本身加载到内存中的代码和数据,

就构成了一个完整的进程。

注意,这些属性在程序的代码和数据中包含吗?

对于大部分程序来说,答案肯定是否定的,

一个硬盘中的死程序怎么知道它的状态呢。

所以PCB的创建和组织是由操作系统来完成的

同样地,PCB实际上是操作系统内核提供的结构

所以一个完整的进程是什么呢,

内核数据结构 + 代码和数据


Linux下的PCB

上面提到,Linux下的PCB叫task_struct的结构体

那这个结构体存放了进程的什么信息呢?

标示符: 描述本进程的唯一标示符,用来区别其他进程。这个好理解,就好比学生管理系统中的每个学生都有一个学号来进行唯一标识,这里的标识符具体就是PID。

状态: 任务状态,退出代码,退出信号等。

优先级: 相对于其他进程的优先级。

程序计数器: 程序中即将被执行的下一条指令的地址。

内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。所以就可以通过内存指针找到进程对应的数据和代码。

上下文数据: 进程执行时处理器的寄存器中的数据。一个进程在执行的过程中难免会产生不少临时数据,而进程不是执行完这个就去执行下一个的,是并发运行的,因为对于优先级相同的进程要有相同的调度,不然相同优先级又何来相统一说呢?就比如A进程执行了10ms,执行完之后它再去后面排队,执行它后面的B进程,执行完10ms之后B进程跑到后面排队,依次往下来......既然进程不是一次就执行完的,它产生的临时数据也是要记录的,所以上下文数据其实就是指向的这一部分。

I/ O状态信息: 包括显示的I/O请求,分配给进程的I/ O设备和被进程使用的文件列表。

记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

其他信息

需要注意,task_struct中的内容远不止于此,

这里只是挑重点的浅浅认识了一下,

如果有兴趣的话可以参考一下大佬的博客:Linux进程管理之task_struct结构体 - zxiaocheng - 博客园 (cnblogs.com)


初见进程

既然对进程有一个大概的轮廓了,

怎么查看一个进程呢?

ps指令查看进程

Linux下可以通过一个简单的指令来查看:

ps axj ,用于查看所有进程的信息:

image-20230106165747987

当然也可以通过grep命令加管道来查看一些具体的信息,

比如我写了一个C语言代码proc.c,

将其编译形成一个可执行程序proc,

程序运行起来成了进程,

就可以用下面的这条命令来查看:

ps axj | grep "proc"

image-20230106171803655

当然如果想显示各个属性的名称还可以再加一句:

ps axj | head -1 & ps axj | grep "grep"

其中head -1是提取文本的第一行,

也就是各个属性的名称:

image-20230106172248489

其中PPID是父进程的ID

PID是当前进程的ID

TTY是进程运行的终端

STAT是当前进程的状态

UID是当前用户的ID

进程在运行的过程中就有了好多属性,很显然这些属性不是一成不变的,

所以进程在调度运行的时候,就具有了动态属性


kill指令挂掉进程

我写的这个代码是一个死循环。

如果是前台运行,可以直接给它用Ctrl C挂掉,

当然,拿到它的PID之后,可以直接用kill命令挂掉:

kill -9 PID

image-20230106173102592

kill命令的好多选项如下,这里不做解释:

image-20230106174603979


通过系统调用接口得到进程的ID(进程标识符)

我们也可以通过系统调用接口在程序内部查看进程的PID(getpid)或PPID(getppid):

image-20230106173802265

image-20230106174006801

image-20230106174131710

相应的还有PPID

PPID就是父进程的PID,没什么好说的,

不过需要注意,从命令行打开的进程,

它的父进程就是命令行bash

image-20230106222149853


从根目录下的proc文件查看进程

执行指令ls /proc

image-20230106175845190

看到了好多数字命名的目录,

而这些目录其实就是进程的PID,

也就是说,一个进程的属性也是数据,

这个数据存在了内存中:

image-20230106180000123

我们可以看到有一个exe文件,

它就指向了进程对应的硬盘上的可执行程序,

当进程挂掉之后,

对应的目录也就被清理掉了:

image-20230106180240627

这里做个小实验;

当一个进程在运行的时候,我们把磁盘上对应的可执行程序删掉,这个进程还能正常运行吗?

初始进程1

可以看到,硬盘中的可执行程序删掉之后进程还在运行,

只是进程对应的目录下的exe指向变成了红色并标注了deleted

所以对于部分进程,

并不依赖硬盘中对应的可执行程序,

当然这个结论并不严谨,

具体问题还需具体分析。


通过fork函数创建子进程

首先认识一下fork函数:

NAME
       fork - create a child process

SYNOPSIS
       #include <unistd.h>
       pid_t fork(void);

RETURN VALUE
       On success, the PID of the child process is returned in the parent, and 0 is returned in the child.  On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.

这里只是浅浅地见识一下,关于具体细节不做讨论。

fork 如果成功创建子进程的话,

会给子进程返回0,给父进程返回子进程的PID。

如果创建失败的话就给父进程返回-1。

那么看下面的代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        printf("我是子进程, pid:%d, ppid:%d\n", getpid(), getppid());
        sleep(1);
    }
    else if (id < 0)
    {
        perror("fork");
        sleep(1);
    }
    else
    {
        printf("我是父进程, pid:%d, ppid:%d\n", getpid(), getppid());
    }
    return 0;
}

运行结果如下;

image-20230107151940133

简单理解一下,子进程创建成功后,

会和父进程一样执行后续的代码,

数据在不修改的情况下会共用。

所以 fork 之后就有了两个进程,

两个进程的 id 不同,

但都会执行下面的 if-else 语句,

所以就有了不同的结果。

至于为什么会这样,不是这里的重点,

这里只是浅浅地认识一下。

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

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

相关文章

事故复盘 | 对不同的ID更新操作竟然也引发死锁?

对不同的ID更新操作竟然也引发死锁&#xff1f; 文章目录对不同的ID更新操作竟然也引发死锁&#xff1f;背景分析初步分析 - 怀疑程序并发问题进一步分析 - 怀疑主键缺失行级锁失效再进一步分析 - 是否存在死锁条件解决方案复盘附录示例的死锁日志常用故障排查 SQL参考链接背景…

webassembly学习

webassemblywebassembly学习基本理论webassembly介绍wasm介绍基本信息wasm会替换javascript么ASM.js&#xff08;wasm的前身&#xff09;将 WebAssembly 作为编程语言的一种尝试wasm应用场景wasm运行原理周边生态WASI 操作系统接口wasi介绍wasmwasi&#xff08;服务端&#xff…

平台总线式驱动开发——基本框架

1. 总线、设备和驱动 硬编码式的驱动开发带来的问题&#xff1a; 垃圾代码太多结构不清晰一些统一设备功能难以支持开发效率低下 1.1 初期解决思路&#xff1a;设备与驱动分离 struct device来表示一个具体设备&#xff0c;主要提供具体设备相关的资源&#xff08;如寄存器地…

ES为什么要移除types类型

文章目录elasticsearch&#xff08;集群&#xff09;中可以包含多个索引index&#xff08;数据库&#xff09; ,每个索引中可以包含多个类型types&#xff08;表&#xff09; ,每个类型下又包含多个文档Document&#xff08;行&#xff09; ,每个文档中又包含多个字段Field&…

姿态估计评价指标

PCK 正确估计出关键点的百分比 &#xff08;Percentage of Correct Keypoints&#xff09;&#xff0c;现在已基本不用。 PCKik∑iδ(did≤Tk)∑i1PCK_i^k\frac{\sum_i\delta(\frac{d_i}{d}\leq T_k)}{\sum_i1} PCKik​∑i​1∑i​δ(ddi​​≤Tk​)​ 检测出的关键点与其对应…

1 机器学习之线性回归

学习笔记自&#xff0c;慕课网 《Python3 入门人工智能》 https://coding.imooc.com/lesson/418.html#mid33109 麻雀虽小&#xff0c;五脏俱全 1.1 回归分析 1.2 线性回归问题求解 1.3 寻找最合适的 a、b&#xff0c;引入损失函数的概念 尽可能使损失函数最小即找到了最合适的…

(重要)实数域上一切范数等价的证明

证明&#xff1a;实数域上一切范数等价编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;首先需要明确范数等价的条件&#xff0c;这里的条件等价于夹逼&#xff0c;就是A小于等于B&#xff0c;B小于等于A&#xff0c;那么A肯定等于B。利用这个…

【MySQL】InnoDB存储引擎的行结构

文章目录前言1、MySQL的体系结构2、InnoDB逻辑存储结构3、InnoDB记录行结构3.1、概述3.2、语法操作3.3、Compact行格式3.3.1、示意图3.3.2、记录的额外信息3.3.3、记录的真实数据3.3.4、定长字段补充3.4、行溢出前言 MySQL服务器上负责对表中数据的读取和写入工作的部分是存储…

【博学谷学习记录超强总结,用心分享|产品经理基础总结和感悟14】

TOC 第三章&#xff0c; 内容服务平台优化思考 前文中&#xff0c;我们粗略分析了用户阅读内容的诉求和创作者编制内容的诉求&#xff0c;本章笔者尝试结合用户诉求分析平台的内容分发策略&#xff0c;结合创作者诉求分析创作者后台设计思路&#xff0c;创作者后台分析主要从…

Java实现支付宝支付,内网穿透,支付功能实现-57

一&#xff1a;支付业务 1.1 支付宝业务简介 1&#xff09;网页跳转到支付宝收银台页面。用户可以使用支付宝App扫一扫屏幕二维码&#xff0c;待手机提示付款后选择支付工具输入密码即可完成支付&#xff1b; 2&#xff09;如果不使用手机支付&#xff0c;也可以点击上图右侧…

Visual Studio解决方案中添加src文件夹的方法

如标题&#xff0c;这个听起来是一个愚蠢的问题&#xff0c;但如果在Visual Studio想添加一个src文件夹&#xff0c;而命名空间不包含src的话&#xff0c;似乎还真不容易。 如果在Visual Studio里新建一个空白解决方案&#xff0c;然后右键解决方案->添加->新建解决方案…

鲲鹏BigData Pro解决方案中Hive组件的部署

1 介绍 本博文基于《鲲鹏Bigdata pro之Hive集群部署》的实验手册进行&#xff0c;目的是方便Hive学习者重用&#xff08;从本文复制&#xff09;相关的指令、配置和代码。同时&#xff0c;会对相关的Bash命令解释&#xff0c;达到增进理解的目的。 2 Hive组件的部署 部署的前…

探索SpringMVC-HandlerAdapter之RequestMappingHandlerAdapter-参数解析

前言 上回&#xff0c;我们大概讲了下HandlerAdapter。今天带大家来认识一下&#xff0c;我们最常用的RequestMappingHandlerAdapter。不过只能给大家先开个头&#xff0c;讲下参数解析。 RequestMappingHandlerAdapter 在介绍HandlerAdapter时&#xff0c;我们就知道Handle…

自己动手写编译器:从NFA到DFA

上一节我们完成了使用NFA来识别字符串的功能。NFA有个问题就是其状态节点太多&#xff0c;使用起来效率不够好。本节我们介绍一种叫“子集构造”的算法&#xff0c;将拥有多个节点的NFA转化为DFA。在上一节我们描述的epsilon闭包操作可以看到&#xff0c;实际上所有由epsilon边…

「ARM32」MMU和页表的映射过程详解

在ARM32中&#xff0c;MMU主要完成虚拟地址到物理地址的映射&#xff0c;并且能够控制内存的访问权限&#xff0c;而页表是实现上述功能的主要手段。页表又分为一级页表、二级页表&#xff0c;在ARM64中甚至还有三级页表。为了便于理解&#xff0c;本章主要讲述一级页表完成段映…

centos7 安装Mysql详细教程

centos7 弃用了Mysql&#xff0c;默认安装了MariaDB&#xff0c;MariaDB是Mysql一个分支&#xff0c;所以要想在centos上安装Mysql&#xff0c;需要先进行卸载MariaDB&#xff0c;避免冲突 本次教程所用环境&#xff1a; 腾讯云服务器&#xff1a;centos7Mysql5.7 1. 卸载Ma…

dubbo源码实践-protocol层-invoker理解

1概述Invoker官方解释&#xff1a;Invoker 是实体域&#xff0c;它是 Dubbo 的核心模型&#xff0c;其它模型都向它靠扰&#xff0c;或转换成它&#xff0c;它代表一个可执行体&#xff0c;可向它发起 invoke 调用&#xff0c;它有可能是一个本地的实现&#xff0c;也可能是一个…

Python 机器学习最常打交道的 27 款工具包

为了大家能够对人工智能常用的 Python 库有一个初步的了解&#xff0c;以选择能够满足自己需求的库进行学习&#xff0c;对目前较为常见的人工智能库进行简要全面的介绍。 1、Numpy NumPy(Numerical Python)是 Python的一个扩展程序库&#xff0c;支持大量的维度数组与矩阵运算…

Maix Bit(K210)保姆级入门上手教程

Maix Bit&#xff08;K210&#xff09;快速上手 这是K210快速上手系列文章&#xff0c;主要内容是&#xff0c;设备连接&#xff0c;环境准备&#xff0c;运行第一个程序 阅读文章前提&#xff1a;python基础,K210是使用Micropython脚本语法的&#xff0c;因此需要一些python…

RocketMQ5.0.0部署与实例

一、Idea调试1.相关配置文件在E:\rocketmq创建conf、logs、store三个文件夹。从RocketMQ distribution部署目录中将broker.conf、logback_namesrv.xml、logback_broker.xml文件复制到conf目录。如下图所示。其中logback_namesrv.xml、logback_broker.xml分别是NameServer、Brok…