深入浅出:进程管理的艺术

目录

进程的定义

进程的特征

进程的状态

进程与程序的区别

进程的控制和管理

进程的特点

1. 虚拟内存空间的分配

2. 时间片轮转调度

图解:

进程段

数据段(Data Segment)

正文段(Text Segment)

堆栈段(Stack Segment)

进程分类

交互进程

批处理进程

守护进程

进程状态

进程状态切换

C语言中进程函数

 创建进程fork

fork() 调用总结

注意事项

 

回收进程wait waitpid

参数说明

返回值

退出进程exit _exit

获取进程号 getpid getppid

总结:


进程的定义

进程可以被视为一个执行中的程序实例,它包含了程序代码、数据集以及一个描述其状态和控制信息的进程控制块(Process Control Block, PCB)。操作系统通过PCB来跟踪和控制进程的执行状态,包括进程的ID、内存映射、打开的文件、状态信息等。

进程的特征

  1. 动态性:进程是程序的一次执行过程,有创建、执行和消亡的生命周期。
  2. 并发性:多个进程可以并发执行,共享处理器和其他系统资源。
  3. 独立性:每个进程都有自己独立的内存空间和系统资源,相互之间不受影响。
  4. 异步性:进程的执行是异步的,即进程的执行速度不可预知,受到多种因素的影响。

进程的状态

进程在其生命周期中会处于不同的状态,主要包括:

  1. 就绪状态:进程已经准备好执行,等待CPU资源。
  2. 执行状态:进程正在使用CPU执行指令。
  3. 阻塞状态:进程因为等待某种事件(如I/O操作完成)而暂时不能执行。

进程与程序的区别

  • 程序是一组指令的集合,是静态的;而进程是程序在某个数据集上的一次执行过程,是动态的。
  • 程序是永久的,存储在磁盘上;进程是暂时的,存在于内存中,随程序的启动而创建,随程序的结束而消亡。

进程的控制和管理

操作系统负责管理和控制进程,主要包括:

  • 进程创建:操作系统为新进程分配资源,初始化PCB。
  • 进程调度:决定下一个执行的进程,将CPU分配给进程。
  • 进程同步:协调多个进程对共享资源的访问,防止冲突。
  • 进程通信:允许进程间交换信息,支持进程协同工作。
  • 进程终止:回收进程占用的资源,结束进程的生命周期。

进程的特点

1. 虚拟内存空间的分配
  • 虚拟地址空间:在典型的32位系统中,进程拥有一个4GB的虚拟地址空间,这个空间被分为两部分:
    • 用户空间(0-3GB):这部分空间专属于每个进程,用于存放代码、数据、堆和栈等,是进程的私有区域,其他进程无法直接访问。
    • 内核空间(3-4GB):这部分空间是所有进程共享的,主要存放操作系统内核代码和数据结构。当进程需要与内核交互时,如进行系统调用,会进入内核空间。
2. 时间片轮转调度
  • 时间片调度:操作系统采用时间片轮转(Round Robin, RR)调度策略来管理多个进程。每个进程在获得CPU执行权时,会被分配一个固定的时间片(通常几毫秒到几十毫秒不等),在此期间,进程独占CPU资源执行。
  • 多任务处理:通过快速地在多个进程之间切换执行(时间片轮转),操作系统可以给用户创造出多任务并行执行的错觉,即使在单核CPU上也能实现高效的多任务处理。
图解:

进程段

数据段(Data Segment)

  • 存储内容:数据段主要用于存储进程中的全局变量、静态变量以及动态分配的内存。全局变量是指在程序的多个函数间共享的数据,而静态变量则是在函数外部声明但在函数内部使用的变量,它们在程序的整个生命周期中都保持有效。

  • 动态数据分配:使用如 malloccallocreallocfree 等函数动态分配的内存也位于数据段中,这部分内存通常被称为“堆”(Heap),它提供了灵活的内存管理能力,允许程序在运行时根据需要动态地分配和释放内存空间。

正文段(Text Segment)

  • 存储内容:正文段,也称作代码段或文本段,主要用于存储程序的可执行代码。这些代码是预先编译好的机器指令,由操作系统加载到内存中供 CPU 执行。正文段通常具有只读属性,以防止程序意外修改自己的代码,从而提高程序的稳定性和安全性。

堆栈段(Stack Segment)

  • 存储内容:堆栈段是用于存储函数调用过程中产生的临时数据的区域,主要包括:
    • 函数的局部变量:这些变量在函数调用时创建,在函数退出时销毁。
    • 函数调用的参数:当一个函数被调用时,其参数会按照一定的顺序压入堆栈。
    • 返回地址:记录调用者的位置,以便函数执行完毕后返回到正确的指令处继续执行。
  • 工作原理:堆栈段遵循“先进后出”(LIFO, Last In First Out)的原则,通过压栈(PUSH)和弹栈(POP)操作来管理数据的进出,这种机制简化了函数调用的管理,使得函数调用和返回的控制流更加清晰和高效。

进程分类

交互进程

  • 特性与用途:交互进程通常由 shell 启动,直接与用户交互,响应用户输入并展示输出结果。这类进程既可以运行在前台,占据用户的终端界面,也可以运行在后台,不干扰用户的其他操作。典型的交互式进程包括 shell 命令、文本编辑器(如 vi 或 nano)、图形界面应用程序等。

批处理进程

  • 特性与用途:批处理进程不直接与用户交互,它们通常被提交到一个队列中,按顺序执行。这类进程主要用于处理大量数据或执行长时间运行的任务,如批量数据处理、备份作业、系统维护任务等。由于不需要用户实时干预,批处理进程可以高效利用系统资源,避免因用户交互而引起的中断和延迟。

守护进程

  • 特性与用途:守护进程是长期运行在后台的服务进程,它们在系统启动时被激活,持续运行直到系统关闭。守护进程不依附于任何终端,主要负责提供系统级的服务,如网络服务(HTTP、FTP)、系

进程状态

  1. 新建状态(New): 当一个进程被创建时,它首先进入新建状态。此时,操作系统为其分配必要的资源,如内存、文件描述符等,并初始化进程控制块(PCB)。进程尚未被调度执行。

  2. 就绪状态(Ready): 进程已经准备好执行,但由于当前CPU正忙于其他进程,它需要等待调度器的调度。在就绪状态下的进程位于就绪队列中,等待CPU时间片。一旦被调度,进程将从就绪状态转变为执行状态。

  3. 执行状态(Running): 进程正在使用CPU执行指令。在多任务操作系统中,执行状态的进程可能很快就会因为时间片到期、更高优先级的进程就绪或进程自身请求I/O操作等原因而转变为其他状态。

  4. 阻塞状态(Blocked): 也称为等待状态或睡眠状态。当进程在执行过程中遇到I/O操作或其他需要等待的事件时,它会主动或被动地进入阻塞状态。此时,进程放弃CPU使用权,等待相应的事件发生,如I/O操作完成、信号量变为可用等。阻塞状态下的进程不参与CPU调度,直到阻塞原因解除。

  5. 僵尸状态(Zombie): 当一个子进程结束执行但其父进程尚未对其进行善后处理(如调用 wait()waitpid() 函数)时,子进程会进入僵尸状态。僵尸进程仍然占用一部分系统资源,如进程表中的一个条目,但不再占用CPU时间,也不会执行任何指令。

  6. 终止状态(Terminated): 进程执行完毕或因异常而终止后,会进入终止状态。在终止状态下,进程实际上已经停止运行,但其状态信息仍保留在系统中,直到父进程清理这些信息(通过调用 wait()waitpid())。清理后,进程完全消失,释放所有资源。

进程状态切换

进程创建后,进程进入就绪态,当CPU调度到此进程时进入运行态,当时间片用完时,此进程会进入就绪态,如果此进程正在执行一些IO操作(阻塞操作)会进入阻塞态,完成IO操作(阻塞结束)后又可进入就绪态,等待CPU的调度,当进程运行结束即进入结束态。
 

C语言中进程函数

 创建进程fork

pid_t fork(void);
功能:创建子进程
返回值:
    成功:在父进程中:返回子进程的进程号 >0
         在子进程中:返回值为0
    失败:-1并设置errno

  1. 资源与状态的继承与分离

    • 子进程几乎完全复制了父进程的执行上下文,包括代码段、数据段、栈段、文件描述符等,但它们拥有独立的进程ID(PID)和父进程ID(PPID)。这意味着子进程继承了父进程的运行环境,但二者在系统层面是完全独立的实体。
  2. 独立的地址空间与数据独立性

    • 尽管子进程继承了父进程的内存映像,但它拥有自己独立的地址空间。因此,对全局变量、静态变量的修改在各自进程中是独立的,互不影响。这种隔离性确保了进程间的数据安全。
  3. 孤儿与僵尸进程的处理

    • 若父进程在子进程之前终止,子进程将被系统中的初始化进程(init)收养,成为孤儿进程。孤儿进程会继续执行,直到自然结束或被其他进程显式终止。
    • 当子进程结束,但父进程未能及时回收其资源时,子进程会变成僵尸进程。僵尸进程虽已结束,但仍占用系统资源,直到父进程通过 wait() 或 waitpid() 系统调用来回收为止。应避免产生僵尸进程,以维持系统资源的高效利用。
  4. 文件描述符的共享与独立操作

    • 子进程继承了父进程打开的文件描述符,这意味着同一文件在父进程和子进程中可通过相同的描述符访问。尽管如此,文件操作(如读写位置)在各自的进程中是独立的,不会互相干扰。

fork() 调用总结

  • 执行流程与返回值

    • fork() 调用在父进程中返回子进程的PID,在子进程中返回0。若返回负数,则表示创建子进程失败。
    • fork() 调用仅执行一次,但它的效果是使得代码在父进程和子进程中分别执行一次,形成两个独立的执行流。
  • 资源复制与独立执行

    • fork() 创建子进程时,子进程获得了父进程的资源副本,包括代码段、数据段和栈段,但拥有独立的地址空间和资源管理。
    • 父子进程在 fork() 后的代码段是独立执行的,即使它们执行相同的指令序列,也不会相互影响。

注意事项

在使用 fork() 创建子进程时,应注意以下几点:

  • 资源管理:确保父进程和子进程妥善管理共享资源,如文件描述符和信号量,以避免资源泄露或竞争条件。
  • 进程清理:父进程应负责回收子进程的资源,避免产生僵尸进程,保持系统资源的健康状态。
  • 信号处理:考虑进程间的信号传递机制,以实现进程间的协调和控制,特别是在异常处理和进程终止时。

 

回收进程wait waitpid

#include <sys/types.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);// 函数原型

pid_t wait(int *status);
功能:回收子进程资源(阻塞)
参数:status:子进程退出状态,不接受子进程状态设为NULL
返回值:成功:回收的子进程的进程号
        失败:-1
        
参数说明
  • pid:用于指定要等待的子进程的 PID(进程ID)或一组进程的选择标准:

    • >0:等待特定 PID 的子进程。
    • -1:等待任意一个子进程,这是最常见的用法。
    • =0:等待与调用进程具有相同进程组 ID 的任意子进程。
    • <-1:等待与 pid 绝对值对应的进程组 ID 相同的任意子进程。
  • status:指向一个整型变量的指针,用于存储子进程的退出状态。如果子进程正常结束,status 中包含的值可以被 WEXITSTATUS() 宏解析得到子进程的退出码;如果是信号导致子进程终止,status 中的值可以被 WTERMSIG() 宏解析得到终止信号。

  • options:指定 waitpid() 的行为模式:

    • 0:默认阻塞模式,父进程将暂停执行,直到子进程结束。
    • WNOHANG:非阻塞模式,立即返回,无论是否有子进程结束。如果无子进程结束,返回 0;否则返回结束子进程的 PID。
返回值
  • 正常情况:返回结束子进程的 PID。
  • 非阻塞模式且没有子进程结束:返回 0
  • 出错:返回 -1,并设置 errno 变量以指示错误原因。

退出进程exit _exit

void exit(int status);
功能:结束进程,刷新缓存
参数:退出的状态
不返回。
void _exit(int status);
功能:结束进程,不刷新缓存
参数:status是一个整型的参数,可以利用这个参数传递进程结束时的状态。
    通常0表示正常结束;
其他的数值表示出现了错误,进程非正常结束


获取进程号 getpid getppid

pid_t getpid(void);
功能:获取当前进程的进程号
pid_t getppid(void);
功能:获取当前进程的父进程号

return: 关键字,在子函数中返回到函数调用的位置,并不结束进程(函数的退出)

exit :函数,不管在子函数还是主函数都会结束进程(进程的退出)

总结:

        在计算中进程是无处不在的,更好的了解进程也可以让我们更好的了解计算机以及编程的原理,文章至此结束,希望可以帮到大家。万分感谢看到这里。

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

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

相关文章

Redis持久化详解

【关闭文件、AOF 刷盘、释放内存这三个任务都有各自的任务队列】所以不是单线程 Redis有两种持久化方案&#xff1a; RDB持久化 AOF持久化 基于Redis集群解决单机Redis存在的问题 【Redis是单进程的】 【也有人做分布式section】 【主从集群中多个从就是做负载均衡的】 …

一维信号全变分(TV)降噪方法(MATLAB)

信号降噪一直是领域研究的热点&#xff0c;这是一项十分有意义并且极具挑战性的工作&#xff0c;经过几十年来相关科研人员的共同努力&#xff0c;降噪技术得到了极大的发展&#xff0c;并在现实生活中也得到了广泛的应用。其中&#xff0c;许多常用的方法有&#xff1a;小波变…

vector模拟实现【C++】

文章目录 全部的实现代码放在了文章末尾准备工作包含头文件定义命名空间和类类的成员变量 迭代器迭代器获取函数 构造函数默认构造使用n个值构造迭代器区间构造解决迭代器区间构造和用n个值构造的冲突拷贝构造 析构函数swap【交换函数】赋值运算符重载emptysize和capacityopera…

上位机网络通讯

目录 一 设计原型 二 后台源码 一 设计原型 二 后台源码 using System; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 上位机网络通讯 {public partial class Form1 : Form{public Form1(){Initializ…

BUG TypeError: GPT2Model.forward() got an unexpected keyword argument ‘past’

TypeError: GPT2Model.forward() got an unexpected keyword argument past’ 环境 transformers 4.38.1详情 这是由于新版的transformers 对GPT2Model.forward() 参数进行了改变导致的错误。具体是past名称改为了 past_key_values 。 解决方法 找到错误语…

黑马点评-Redis的缓存击穿,缓存雪崩,缓存穿透,互斥锁,逻辑过期

文章目录 1.缓存穿透2.缓存雪崩3.缓存击穿3.1 互斥锁3.2 基于逻辑过期 1.缓存穿透 解决办法 写入NULL值到Redis缓存&#xff0c;以后就会命中Redis的控制缓存而不会出现请求直接打到数据库的问题&#xff01; 代码 2.缓存雪崩 这个概念很好理解&#xff0c;雪崩就是无数的…

开发者聊科学作息时间表

非常有幸对科学作息时间表app的开发者做一次采访。 问&#xff1a;你对科学作息时间表app满意么&#xff1f; 答&#xff1a;非常不满意&#xff0c;我们的设想是让他更智能&#xff0c;更多的提醒方式&#xff0c;更好的交互体验。如果作为一个闹钟他是非常不合格的&#xff0…

视图库对接系列(GA-T 1400)三、代码生成

项目准备 我们把需要的第三方包和需要生成的库引入到对应的**基础包**中对应版本号 <properties><java.version>1.8</java.version><httpclient.version>4.5</httpclient.version><httpcore.version>4.4.12</httpcore.version><…

tinyshop项目部署

参考软件测试之测试用例设计&#xff08;四&#xff09;_管理后台 测试用例-CSDN博客 1、下载xampp 2、修改apache和mysql的端口分别为4431 &#xff0c;8013和3306 3、访问页面&#xff1a;输入ip:端口号&#xff0c;出现以下页面即成功 4、安装tinyshop商城 将解压的tinys…

Chart.js四个示例

示例代码在图片后面&#xff0c;点赞加关注&#xff0c;谢谢 条形图 雷达图 折线图 圆环图 完整例子代码 具体代码在干什么看粗体加重的注释 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <me…

OceanBase Meetup北京站|跨行业应用场景中的一体化分布式数据库:AI赋能下的探索与实践

随着业务规模的不断扩张和数据处理需求的日益复杂化&#xff0c;传统数据库架构逐渐暴露出业务稳定性波动、扩展性受限、处理效率降低以及运营成本高等一系列问题。众多行业及其业务场景纷纷踏上了数据库现代化升级之路。 为应对这些挑战&#xff0c;7月6日&#xff0c;OceanB…

搭建个人博客及错误记录

搭建个人博客及错误记录 文章目录 搭建个人博客及错误记录需要用到的网址2.推荐两个参考教学视频3.发布一篇博客个人主题配置的提醒localhost拒绝连接问题解决办法ssh -T gitgithub.com失败问题解决Deployer not found:git解决 可以根据目录解决遇到的相同问题 需要用到的网址 …

德国威步的技术演进之路(下):从云端许可管理到硬件加密狗的创新

从单机用户许可证到WkNET网络浮点授权的推出&#xff0c;再到引入使用次数和丰富的时间许可证管理&#xff0c;德国威步产品不断满足市场对灵活性和可扩展性的需求。TCP/IP浮动网络许可证进一步展示了威步技术在网络时代的创新应用。借助于2009年推出的借用许可证以及2015年推出…

如何选择适合自己的笔记本电脑

在现代社会中&#xff0c;笔记本电脑已经成为人们工作、学习和娱乐的重要工具。然而&#xff0c;面对市场上琳琅满目的笔记本电脑产品&#xff0c;如何选择一款适合自己的笔记本电脑呢&#xff1f;本文将为您提供一些有用的建议。 首先&#xff0c;确定您的使用需求。不同的用户…

新手教学系列——慎用Flask-SQLAlchemy慢日志记录

在使用 Flask-SQLAlchemy 开发应用时,了解和避免潜在的问题是非常重要的。特别是在常驻进程和循环执行任务的场景下,慢查询记录功能(SQLALCHEMYRECORDQUERIES)可能会引发严重的内存泄漏问题。本文将详细介绍这个问题,并提供解决方案,帮助你在开发过程中避免掉入这些陷阱。…

为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}(保姆级包括安装QT)超详细记录版

为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}【保姆级包括安装QT】超详细记录版 Chapter1 为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}(保姆级包括安装QT)超详细记录版一. 安装QT程…

深入了解自动化:聊聊什么项目适合做自动化测试?

自动化测试 什么是自动化测 什么是自动化测试&#xff1f; 随着软件产业的不断发展&#xff0c;市场对软件周期的要求越来越高&#xff0c;于是催生了各种开发模式&#xff0c;如大家熟知的敏捷开发&#xff0c;从而对测试提出了更高的要求。此时&#xff0c;产生了自动化测试…

2024年港澳台联考考生成绩数据分析来啦

分数线 出炉 2024年的港澳台联考正式出分&#xff01;根据考生成绩&#xff0c;全国联招划档线如下&#xff1a; 一、本科批次 &#xff08;一&#xff09;普通类院校&#xff08;专业&#xff09;&#xff1a;文史类365分、理工类390分&#xff08;部分院校执行高分线&#…

算法基础入门 - 2.栈、队列、链表

文章目录 算法基础入门第二章 栈、队列、链表2.1 队列2.2 栈2.3 纸牌游戏2.4 链表如何建立链表?1.我们需要一个头指针(head)指向链表的初始。链表还没建立时头指针head为空2.建立第一个结点3.设置刚创建的这个结点的数据域(左半)和指针域(右半)4.设置头指针,头指针可方便…

10 - matlab m_map地学绘图工具基础函数 - 绘制多边形区域、流线图、散点图和添加注释的有关函数

10 - matlab m_map地学绘图工具基础函数 - 绘制多边形区域、流线图、散点图和添加注释的有关函数 0. 引言1. 关于m_patch2. 关于m_streamline3. 关于m_scatter4. 关于m_annotation5. 结语 0. 引言 本篇介绍下m_map中绘制多边形区域函数&#xff08;m_patch&#xff09;、绘制流…