Linux系统编程:进程的管理和创建

news2024/9/20 7:58:53

目录

一. 什么是进程

二. Linux对进程的管理方法

2.1 PCB描述进程

2.2 进程的组织

2.3 进程的查看 

三. 子进程的创建

3.1 子进程创建函数fork的使用

3.2 子进程创建的原理

四. 总结


一. 什么是进程

进程(process)是指计算机中已经存在并运行的程序,是系统进行资源分配和调度的基本单位,是计算机操作系统结构的基础。我们在Window/Linux启动一个软件,或者在执行一条指令,都会在系统层面创建进程。

在Windows下打开任务管理器(快捷键Ctrl + Shift + Esc),可以查看当前系统中存在的进程。我们可以看到,Windows下的进程被分为了应用进程和后台进程,在Linux下也一样,进程被分为了前端进程和后端进程。

图1.1 通过任务管理器查看Windows下的进程

Linux操作系统要对进程进行管理,管理的原则为先描述后组织,即:要先将进程信息通过结构体描述记录起来,然后再通过特定的数据结构进行组织。每次新创建一个进程,都会在内存再创建一个与之对应的进程控制块PCB(process control block),我们常说的运行程序之前,要现将程序载入内存,不仅仅是将代码和数据载入内存,还有创建对应的PCB。每一个PCB,都指向对应的代码和数据。

我们可以认为,进程 = 对应的数据和代码 + 对应的进程控制块PCB

二. Linux对进程的管理方法

2.1 PCB描述进程

进程控制块,简称PCB,是用于描述进程信息的结构体,不同的操作系统中PCB的名称可能会有所不同,在Linux下,PCB的名称为:struct task_struct {...}

PCB中应当包含进程的如下信息:

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

Linux系统依靠双向链表组织进程信息,PCB的定义大体如下:

struct task_struct
{
    //进程属性信息
    ... ...

    struct task_struct* _prev;   //前一个进程
    struct task_struct* _next;   //后一个进行
}

2.2 进程的组织

Linux要对进程进行管理,就要对进程进行组织,Linux依靠双向链表管理进程控制块PCB,每一个PCB都指向与之对应的代码和数据。

当创建新进程时,新建的PCB要插入到链表中,执行的操作就等同于双向链表节点的插入,时间复杂度为O(1),进程结束或强制终止,就相当于链表节点的删除,进程状态发生改变,就更改PCB中的相应信息。

结论:对进程的管理,本质就是对PCB链表的增删查改。

图2.1 进程的组织

在Linux系统中,还存在运行队列,每当有一个进程载入到内存之中,它的PCB就会被插入到运行队列的尾部等待CPU运行,CPU运行处于运行队列头部的进程。当CPU运行新的进程之前,需要将头部的进程删除(完成全部程序的运行)或者将其挪到运行队列的尾部(还没完成全部程序的运行)。

进程调度,本质就是在task_struct运行队列中选择一个进程的过程。

图2.2 运行队列

2.3 进程的查看 

进程查看的指令:

  • ps -- 查看当前终端下的进程。
  • ps axj -- 查看系统中所有进程。
  • ps axj | grep '...'  -- 查看指定的进程。
  • ps axj | head -1 && ps axj | grep '...' -- 带上头部查看指定进程
  • ps axj | head -1 && ps axj | grep '...' | grep -v grep -- 在查看指定进程的同时去除grep进程

为了方便演示,我们打开两个终端,在一处写死循环.cpp代码,生成可执行文件(取文件名myproc)并运行,在另一处终端使用上面的指令进行进程查看,如图2.3所示。

图2.3 进程查看

使用top指令也可以查看进程,top指令类似于Windows下的任务管理器。

在Linux系统中,每创建一个新的进程,都会在/myproc目录下新建一个目录来记录进程信息,使用ls /proc命令,可以查看/proc文件中的文件,每个目录文件对应一个进程,目录文件的文件名为进程的编号(pid)。

图2.4 查看进程目录

如图2.5所示,将myproc文件运行起来,使用指令ps axj | head -1 && ps axj | grep myproc查看其进程pid,然后通过ll /proc/(pid) 查看这个进程对应的目录中的内容,里面有cwd和exe两个文件,它们的意义为:

  • cwd -> 当前进程的工作路径。
  • exe -> 可执行程序的路径和文件名。
图2.5 进程文件的查看

通过ps相关指令查看进程id相对复杂,我们可以在代码中使用下面的两个函数来查看当前进程和其父进程的id:

  • pid_t getpid() -- 获取当前进程的id。
  • pid_t getppid() -- 获取父进程的id。

上面两个函数,被包在头文件sys/types.h中。

  • 强制终止进程:kill -9 [进程id]

三. 子进程的创建

3.1 子进程创建函数fork的使用

  • 函数原型:pid_t fork(void)
  • 函数返回值:若创建成功,给父进程返回子进程的编号,给子进程返回0,若失败返回-1

在pid_t ret = fork()之后,进程一分为二,一个父进程,一个子进程。

fork()函数的使用一般是希望父进程和子进程执行不同的代码,一般通过if/else if/else体系结构,判断fork()函数的返回值,来区分希望父进程和子进程运行的代码。

如代码3.1所示,使用fork创建子进程,父子进程都死循环打印进程的pid和ppid。如图3.1,我们可以看到,虽然父进程和子进程的代码都是while(1)死循环,但依旧交替运行父子进程的代码,我们无法确定父子进程的运行顺序,也并不是说一个进程要完成其全部运行之后,其他的进程才能够执行。

代码3.1:fork的使用 

1 #include<iostream>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 
  5 int main()
  6 {
  7     pid_t ret = fork();  //创建子进程
  8 
  9     if(ret < 0)
 10     {
 11         //子进程创建失败
 12         perror("fork");
 13     }
 14     else if(ret == 0)
 15     {
 16         //子进程代码
 17         while(1)
 18         {
 19             printf("Child process, ret:%d, pid:%d, ppid:%d\n", ret, getpid(), getppid());
 20             sleep(1);
 21         }
 22     }
 23     else
 24     {
 25         //父进程代码
 26         while(1)
 27         {
 28             printf("Parent process, ret:%d, pid:%d, ppid:%d\n", ret, getpid(), getppid());
 29             sleep(1);                                                                                                        
 30         }
 31     }
 32 
 33     return 0;
 34 }
图3.1 代码3.1的运行结果

3.2 子进程创建的原理

或许有人会问,C/C++函数不是只能有一个返回值吗,为什么父子进程会有两个不同的返回值?之就要设计到fork内部和实现了。

如果3.2所示,我们可以推测,fork内部一定调用了某些系统接口,创建出了子进程,那么,在fork函数返回时,到return处实际上已经分为父进程和子进程了,父进程和子进程的返回值ret不同,就实现了fork对于父子进程的不同返回值。

而创建子进程时,会首先拷贝一份父进程的PCB,然后修改器内部的属性,然后添加到列表中去等待运行。

子进程被创建出来后,父子进程的运行顺序无法确定,具体的进程运行顺序是由Linux系统中的调度器来决定的。

图3.2 子进程创建逻辑

四. 总结

  • 进程是指计算机中已经存在并运行的程序,进程 = 对应的PCB + 对应的代码和数据。
  • 操作系统对进程进行管理时,会先使用task_struct对进行信息描述(PCB),然后使用双向链表对PCB进行组织,对进程的管理,本质上就是对PCB链表的增删查改。
  • 通过ps、top、ls /proc 等指令,可以查看进程信息。通过getpid和getppid函数可以获取当前进程和父进程的id。
  • 通过fork可以创建子进程。

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

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

相关文章

动态规划 DP (一)

1.动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09; 维基百科的定义说的很清楚&#xff1a; 动态规划不能解决所有的问题&#xff0c; 只能应用于有最优子结构的问题。例如背包问题、最长公共子序列问题、最短路径问题等。 最优子结构&#xff1a;局部…

Vue3通信方式之defineProps、defineEmits、useAttrs、插件mitt和v-model

目录 1、使用defineProps2、使用defineEmits接受自定义事件2.1原生DOM事件2.2自定义事件 3、全局事件总线&#xff08;插件mitt&#xff09;4、v-model5、useAttrs 1、使用defineProps props可以实现父子组件通信,在vue3中我们可以通过defineProps获取父组件传递的数据。且在组…

Opencv医学图片分割-以血管、胼胝体MR等分割为例

用到环境 1、pycharm community edition 2022.3.2 2、Python 3.10 后面应该会传代码到资源&#xff0c;比较需要的可以私信我。 总体设计 图1 扩展实验二“医学图像分割”流程图 ## 具体步骤 1. 导入OpenCV和NumPy库 2. 定义阈值分割方法threshold_segmentation&#xff0c;接…

spring框架-概述(spring特性、生命周期)(一)

文章目录 什么是springspring重要特性spring生命周期知识扩展 什么是spring Spring框架是一个开放源代码的J2EE应用程序框架&#xff0c;由Rod Johnson发起&#xff0c;是针对bean的生命周期进行管理的轻量级容器 ,是为了解决企业级编程开发中的复杂性&#xff0c;实现敏捷开发…

[进阶]网络通信:TCP通信-支持与多个客户端同时通信

目前我们开发的服务端程序&#xff0c;是否可以支持与多个客户端同时通信&#xff1f; &#xfeff;不可以的。&#xfeff;因为服务端现在只有一个主线程&#xff0c;只能处理一个客户端的消息。 代码演示如下&#xff1a; 客户端&#xff1a; public class Client {public…

SpringBoot 异常处理的最佳实践

SpringBoot 异常处理的最佳实践 在 Web 开发中&#xff0c;异常处理是非常重要的一环。在 SpringBoot 框架中&#xff0c;异常处理方式有很多种&#xff0c;但是如何选择最佳实践呢&#xff1f;本文将介绍 SpringBoot 异常处理的最佳实践&#xff0c;并附带代码示例。 异常处理…

flutter - 编写 阿里云-金融级实名认证插件

项目中有实名认证的需求&#xff0c;用户上传身份证反正面&#xff0c;进行人脸核验&#xff0c;后台集成的是阿里云的金融级实名认证SDK&#xff0c;巧合的是阿里云没有packages 需要自己造轮子。 废话不多少&#xff0c;直接上代码&#xff1a; 新建项目 ProjectType Plugin…

网站图片优化技巧及最佳实践

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言使用适当的图片格式…

0017-TIPS-pawnyable : eBPF

原文 BPFの導入 検証器とJITコンパイラ eBPFのバグの悪用 题目下载 BPF介绍 BPF 在介绍eBPF之前&#xff0c;先介绍其前身BPF。 随着时代的发展&#xff0c;BPF的用途越来越广泛&#xff0c;扩展也越来越多。在重大更改后的BPF有时被称为eBPF&#xff08;扩展BPF&#xff09…

路漫漫其修远兮,吾将上下而求索

路漫漫其修远兮&#xff0c;吾将上下而求索 一、坚定信念二、持之以恒地努力三、谦虚和学习的态度四、上下而求索也要遵循道德底线和原则五、建立合适的人际关系和互助机制六、坚定自己的信仰和信念七、个人经验与体会 路漫漫其修远兮&#xff0c;吾将上下而求索——这句话不仅…

python期末上机题:

1、编写Python程序&#xff0c;创建类Temperature&#xff0c;其包含成员变量degree&#xff08;表示温度&#xff09;以及实例方法ToHuaShiDu()和ToSheShiDu&#xff0c;并编写测试代码。 程序运行示例&#xff1a; 请输入摄氏温度&#xff1a;30 摄氏温度 30.0&#xff0…

栈和队列(一)

文章目录 顺序表&#xff0c;链表的有点和缺点链表顺序表 栈和队列栈的实现栈的应用&#xff08;括号匹配问题&#xff09; 顺序表&#xff0c;链表的有点和缺点 链表 优点&#xff1a; 1、任意位置插入删除&#xff0c;时间复杂度位O(1) 2、按需申请释放空间 缺点&#xff1a…

Prompt Engineering 面面观

作者&#xff1a;紫气东来 项目地址&#xff1a;https://zhuanlan.zhihu.com/p/632369186 一、概述 提示工程&#xff08;Prompt Engineering&#xff09;&#xff0c;也称为 In-Context Prompting&#xff0c;是指在不更新模型权重的情况下如何与 LLM 交互以引导其行为以获得…

Latex长表格

示例一&#xff1a; 输出一个长表格的示例。 代码&#xff1a; \documentclass[jou,apacite]{apa6} \usepackage{multirow} \usepackage{array} \newcolumntype{P}[1]{>{\centering\arraybackslash}p{#1}} \usepackage{longtable}%\usepackage{showframe} % to visualize…

极致呈现系列之:Echarts漏斗图的流光溢彩

目录 什么是漏斗图漏斗图的特点及应用场景漏斗图的特点漏斗图常见的的应用场景&#xff1a; Echarts中漏斗的常用属性Vue3中创建漏斗图美化漏斗图样式 在数据分析和可视化中&#xff0c;我们经常需要比较不同阶段的数据比例或流程的渐进筛选过程。漏斗图作为一种专门用于展示这…

Qt使用技巧--定义Private类

如果查看Qt的源码&#xff0c;会发现很多类都会有一个***Private类。这是Qt用于封装私有操作的一种设计模式。 给出一个继承自QObject的Private类具体的实现&#xff1a; MyClass.h #include "QObject"class MyClassPrivate; class MyClass: public QObject{ Q_OB…

LangChain让LLM连接更多能力

随着LLM&#xff08;Large language models &#xff09;的发展&#xff0c;不仅仅出现了很多新的应用&#xff0c;一些开发框架也发展很快&#xff0c;典型的就是本文介绍的项目——LangChain&#xff0c;目前LangChain几乎一天一个版本&#xff0c;几个月时间Star数目已经49k…

<C++> C++11 Lambda表达式

C11 Lambda表达式 1.C98中的一个例子 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。 #include <algorithm> #include <functional> int main() {int array[] {4, 1, 8, 5, 3, 7, 0, 9, 2, 6};// 默认按照小于…

软考:软件工程:面向对象技术与UML,时序图,用例图,类对象,封装,继承,多态

软考&#xff1a;软件工程: 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &#xff08;1&#…

iOS 集成Jenkins pipeline 完整流程

文章目录 一 创建一个Jenkins pipeline 项目配置分支参数在工程中添加 ExportOptions.plist 文件创建放置打包文件的文件夹在工程里面添加shell脚本文件配置pipeline sript构建 一 创建一个Jenkins pipeline 项目 配置分支参数 选择参数化构建构成&#xff0c;如上图所示&#…