Linux下进程及其进程地址空间以及一些进程的控制函数

目录

    • 什么是进程?
    • 进程的状态
        • Linux下进程的状态
    • 进程地址空间
      • 什么是进程地址空间
        • 为什么需要进程地址空间?
    • 进程控制
      • 进程控制函数
        • fork
        • wait/waitpid 进程等待
        • 进程替换,进程替换函数exe

今天我们来分享一下Linux下的进程和进程地址空间以及一些进程的控制函数。

什么是进程?

进程是操作系统分配资源的基本单位,一个进程是一个程序的一次执行过程。每启动一个进程,操作系统就会为它分配一块独立的内存空间,用于存储PCB、数据段、程序段等资源。每个进程占有一块独立的内存空间。简单来说,它就是可执行程序 + 该进程对应的内核的各种数据结构。

问:操作系统是怎么管理进程的呢?

再回答这个问题之前,我想问问学校是怎么管理学生的呢?,总不能一个一个盯着吧;高效的做法就是将学生的信息用一个类似结构体的东西给记录起来,然后用一个类似链表的结构给串起来,那么学校管理学生,其实就是对这个数据结构的增删查改的。
那么操作系统肯定也是类似的,将进程信息放进一个叫做进程控制块的数据结构中,其实就是个结构体,称为PCB,Linux操作系统下,这个数据结构名字叫做task_struct;它会被装载到RAM(内存)里并且包含着进程的信息。然后把一个一个的task_struct用链表组织起来进行管理。

进程的状态

什么叫做进程的状态呢?举个例子吧,学校的学生有在读,退学,停学,毕业等等,这些状态;那么为什么要标识这些状态呢?当然就是为了好管理啊;所以进程的状态也类似,也就是为了方便操作系统根据进程的状态进行管理。
但是不同的平台下,进程的状态也有所不同,但是无非也就是运行态,终止态,阻塞态,挂起态啊这些;在讲Linux操作系统下进程的状态之前,我们先来认识上面举例的这几个吧。

  • 运行态:进程的PCB在运行队列就叫做运行态(代表进程条件已经就绪,随时可以被调度)
  • 终止态:进程还在,只是不会再次运行了,随时等待被释放
  • 阻塞态:当进程在等待外部资源时,该进程条件不就绪,代码不会执行,进入对应设备的等待队列,此时进入阻塞状态
  • 挂起态:短期内不会被调度(该进程所等待的资源,短期内不会就绪)的进程;如果让它的代码和数据依旧在内存中,那就是浪费内存空间,OS就会把该进程的代码和数据置换到磁盘上(置换到磁盘的swap分区)。这个过程就叫做进程挂起

对于上面的解释,可能大家还不是很理解,那就跟着我解决几个问题,就能理解了
为什么需要终止态,既然这个进程都不会在运行了,直接退出,回收资源不行吗?

答:你进程执行的结果,执行是否成功,退出的信息,是不是要告诉OS或者是父进程呢?而且如果但是操作系统很忙,没空去释放你这个进程呢?所以就要先进入终止态,等待操作系统空闲了,再去读取进程的退出信息,释放进程。
怎么理解外部资源不就绪,进入阻塞状态呢?
一个进程在使用资源的时候,可不只是在申请CPU资源,可能还会申请其他资源,比如说磁盘啊,网卡啊,显示器啊等等;那么如果有多个进程其他资源已经就绪,但是要申请CPU资源,暂时无法满足,那就需要排队——运行队列。所以如果当进程访问某些资源时,如果该资源没有准备好或者正在给其他进程提供服务,此时当前进程就要从运行队列中移除;将当前进程的task_struct放入对应设备的描述结构体中的等待队列
在这里插入图片描述
在这里插入图片描述

Linux下进程的状态

我们直接来看看,Linux描述进程状态的源码

static const char *task_state_array[]={"R (running)","S (sleeping)","D (disk sleep)","T (stopped)","T (tracing stop)","Z (zombie)","X (dead)"
};
  • R(running):运行状态
  • S(sleeping):阻塞状态,(这是浅度的睡眠,也叫做可中断睡眠,意思就是这个进程在等待资源,但是操作系统可以随时唤醒它,你也可以终止它)
  • D(disk sleep):也是一种阻塞状态(一般来说,在Linux中,如果我们等待的是磁盘资源,我们进程阻塞所处的状态就是D);这个叫深度睡眠,也叫做不可被中断睡眠,这种状态下,除非关机重启,不然这个进程不会被杀死。
  • Z(zombie):僵尸状态,在Linux系统下,进程退出时,一般不会直接进行X状态(死亡,资源可以立马回收),而是进入Z状态
  • X(dead):死亡状态,表示进程可以被释放,随时等待被释放,这个状态只是一个返回状态,你不会在任务列表里看到这个状态
  • T(stopped):停止状态,暂停;可以通过发送信号来暂停进程,暂停后进程就进入这个状态,也可以发送信号让这个进程继续执行
  • T(tracing stop):这个也是一种暂停状态,gdb在调试程序时,gdb进程处于S状态等待输入,但是我们发现我们自己的进程所处的状态就是T(tracing stop)状态。
    为什么呢要先进入Z状态呢?

首先明确进程为什么被创建出来,一定是因为要有任务让这个进程执行,当该进程退出时,我们怎么知道,这个进程把任务给完成了呢?所以一般需要将进程的执行结果告知给父进程和OS,所以进程进入Z状态,就是为了维护退出信息,可以让父进程或者os读取的.

长时间的僵尸状态会有什么问题呢?

如果没有人回收子进程的僵尸,该状态会一直维护,该进程的相关资源(task_struct)不会被释放,内存泄
露,一般必须要求父进程进行回收

这里在补充一个概念“孤儿进程”

什么叫做孤儿进程呢?

如果父进程提前退出,子进程还在运行,就叫孤儿进程,子进程就会被操作系统领养,有操作系统负责回收。

进程地址空间

进程地址空间,我们需要搞懂两个问题即可。第一个什么是进程地址空间?第二个就是为什么需要进程地址空间?

什么是进程地址空间

所谓进程地址空间,是操作系统上的概念,物理上并不真实存在。

每一个进程在启动时,都会让操作系统给他创建一个地址空间,该地址空间就是进程地址空间。

其实进程地址空间就是内核的一个数据结构叫做,struct mm_struct。通过这个数据结构,维护进程需要的资源的区域,比如堆,栈等,这些区域记录的都是虚拟地址,然后可以通过页表将虚拟地址映射到物理内存地址

有了进程地址空间可以很好的保证进程的独立性(多进程运行,需要独享各种资源,多进程运行期间互不干扰);
这样干讲可能不太懂,我们来看图
在这里插入图片描述
那我们来讲讲进程地址空间也就是mm_struct里面的内容大概是什么吧,其实就是mm_struct中维护了一个链表,然后这个链表的结点都是每段空间的划分,比如 (栈区 start 和 end)-> (堆区 start 和 end) -> (正文代码 start 和 end),如果要执行这个进程的某段代码,就去 mm_struct 中维护的链表中找 (正文代码)对应的区域,然后通过页表可以得到相应的内存地址,将程序的代码和数据读取到 CPU 中进行执行而程序内部的地址通过加载的时候早已转化成了虚拟地址。

为什么需要进程地址空间?

  1. 保护内存

有了虚拟地址空间,相当于给访问内存添加了一层保护层,可以对转换过程进行审核,对于非法的访问,就直接拦截了

  1. 通过地址空间,进行功能模块的解耦

(1)如果没有虚拟内存空间,那么如果一个进程正在malloc来申请内存空间,就会去调用malloc的底层代码,进行内存管理要进行的工作
(2)而现在,如果malloc来申请空间,那么操作系统会将进程中虚拟空间中对应的堆区扩大相应的大小,允许用户访问这段空间,但是不会马上进行内存的分配。而是等到用户真正要使用这块内存空间时,才会触发内存管理,申请物理空间,建立映射关系,就可以进行两者的解耦。
(3)如果没有进程地址空间,进程直接访问物理内存,当进程退出时,内存管理需要尽快将该进程回收,在这个过程中必须保证内存管理得知道某个进程退出了,并且内存管理也得知道某个进程开始了,这样才能给他们及时的分配和回收资源,这就意味着内存管理和进程管理模块是强耦合的。
(4)如果有了进程地址空间,当一个进程需要资源的时候,通过页表映射去要就可以了,内存管理就只需要知道哪些内存区域(配置)是无效的,哪些是有效的(被页表映射的就是有效的,没有被页表映射的就是无效的),当一个进程退出时,它的映射关系也就没有了,此时没有了映射关系,物理内存这里就将该进程的数据设置为无效.

就相当于,你存了1万块钱,你银行卡就有余额,银行管理你的1万块钱,你不用关心你1万块钱被拿去干嘛,你只需要在需要时,取就行了

  1. 让进程或者程序可以以统一的视角看待内存(方便一统一的方式来编译和加载所有的可执行程序,也就是说,无论是怎样的代码,都认为我们需要什么区域,都到各种的区域去,比如代码区,永远都在虚拟地址空间的那个区,而如果直接加载到内存,那么今天这个可执行程序的代码区可能加载到内存的这个位置,明天又可能是这个位置)
  2. .内存共享:虚拟地址空间允许多个进程访问同一块物理内存,这种机制可以提高进程间通信的效率和灵活性
  3. 进程间独立:每个进程拥有自己独立的地址空间,使得进程之间相互独立,避免了进程之间的影响和冲突。

进程控制

进程控制函数

fork

它有两个返回值,创建子进程成功返回给子进程0,失败返回-1;创建成功返回子进程Id给父进程,失败返回-1。
问:fork之后,操作系统会做什么?

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程的task_struct到系统进程列表当中
  • fork返回,开始调度器调度
  • 数据以写时拷贝的方式,来进行进程共享或独立
    那什么是写时拷贝呢?
    通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本,重新建立了映射关系
    在这里插入图片描述
    在这里插入图片描述
    这里我们就能解释为什么fork有两个返回值,pid_t id,同一个变量,怎么会有两个不同的值呢?
    当id=fork()的时候,谁先返回,谁就要发生写时拷贝,所以,同一个变量,会有不同的内容值,本质就是因为虚拟地址是一样的,但是映射到物理地址的时候,就不一样了。

wait/waitpid 进程等待

为什么要进程等待?

  • 子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
  • 父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,执行结果怎么样啊, 是否正常退出啊。
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

wait方法:pid_t wait(int* status):

返回值:成功返回被等待进程pid,失败返回-1。
参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

wait()的方案可以解决回收子进程z状态,让子进程进入x

wait作用:等待任意一个退出的子进程

waitpid方法:pid_ t waitpid(pid_t pid, int *status, int options);

返回值:当正常返回的时候waitpid返回收集到的子进程的进程ID;如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:

  • pid:Pid=-1,等待任一个子进程。与wait等效,Pid>0.等待其进程ID与pid相等的子进程。
  • status:WIFEXITED(status)(等价于(status)&0x7F): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出);WEXITSTATUS(status)(等价于(status>>8)&0xFF): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
  • options:WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程id;0表示阻塞等待

进程替换,进程替换函数exe

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数 以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动 例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

#include <unistd.h>`int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

为什么需要进程替换?

我们想让创建出来的子进程,执行全新的程序,这个时候就需要程序的程序替换

进程替换的原理

  1. 将磁盘中的程序,加载入内存结构
  1. 重新建立页表映射,那个进程执行程序替换,就重新建立映射(子进程)
    效果:让我们的父进程和子进程彻底分离,并让子进程执行一个全新的程序

需要注意的是,进程替换之后,原来共享的父进程代码就不会再执行了
** 子进程执行程序替换,会不会影响父进程呢,如果不影响,是怎么做到的呢?**

不会(进程具有独立性),数据层面发生写时拷贝,当程序替换的时候,我们可以理解成代码和数据都发生了写时拷贝完成父子分离。

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

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

相关文章

运维小白必学篇之基础篇第十一集:系统进程实验

系统进程实验 实验作业&#xff1a; 1、利用top命令查看当前系统进程&#xff0c;要求没5秒刷新一次&#xff0c;分别按照CPU使用率&#xff0c;内存使用量&#xff0c;CPU使用时间&#xff0c;PID分别排序一次 每5秒刷新一次&#xff1a;top -d 5 按照CPU使用率排序&#xf…

一个好用的不基于时间的同步文件的软件 —— Allway sync 文件同步

文件同步是协作同步的基础。 对于多文件修改后的同步备份,如果不是同步到网盘,那种有网盘软件帮助,识别修改后文件,并备份。容易出现备份出错&#xff0c;人就容易麻&#xff0c;麻中麻。 基本需求 对于文件的同步需求&#xff0c;如下&#xff1a; 识别更新后的文件&#…

android 时间同步软件,Network Time(时间同步软件)

Network Time(时间同步软件)是一款专业用以互联网技术多台计算机的系统时钟同步软件&#xff0c;运用Network Time可以完成服务器和局域网络的時间做到ms级的精确&#xff0c;有必须的可以下载应用。 【基础介绍】 Network Time是由 Han-soft发布的一款功能齐全的时间同步系统&…

时间同步软件和相关网站

网站 国家授时中心 http://www.time.ac.cn/stime.asp Time.is - 任何时区的精确时间 https://time.is/ 软件 时间精灵——WEB在线时间发布与校准Timefairy.exe 官网&#xff1a;http://www.time.ac.cn/times/timefairy.htm 下载&#xff1a;http://www.time.ac.cn/serve/down…

韶关python培训班_“韶”字的五行属性是什么?

韶字五行属性及含义 拼音&#xff1a;shao (姓氏)繁体&#xff1a;韶笔画&#xff1a;14五行属性&#xff1a;金吉凶&#xff1a;吉 韶〈名〉 (形声。从音,召声。本义:传说中的虞舜时代的乐曲名) 传说舜所作的乐曲名 [name of music composed by Emperor Shun] 韶,虞舜乐也…

目标检测算法:Faster-RCNN论文解读

目标检测算法&#xff1a;Faster-RCNN论文解读 前言 ​ 其实网上已经有很多很好的解读各种论文的文章了&#xff0c;但是我决定自己也写一写&#xff0c;当然&#xff0c;我的主要目的就是帮助自己梳理、深入理解论文&#xff0c;因为写文章&#xff0c;你必须把你所写的东西表…

N-propargyloxycarbonyl-L-lysine,1215204-46-8,是一种基于赖氨酸的非天然氨基酸 (UAA)

产品描述&#xff1a; N-ε-propargyloxycarbonyl-L-lysine (H-L-Lys(Poc)-OH) 是一种基于赖氨酸的非天然氨基酸 (UAA)。 广泛用于多种生物体中荧光探针的生物偶联。 N- ε- Propargyloxycarbonyl-L-lysine (H-L-Lys (Poc) - OH) is a non natural amino acid (UAA) based on …

Qt6之调用Windows下vc生成的动态链接库dll

Qt是跨平台工具&#xff0c;显然能和windows的动态库一起使用。 在Windows操作系统上&#xff0c;库以文件的形式存在&#xff0c;并且可以分为动态链接库(DLL) 和静态链接库两种。动态链接库文控以.dll为后缀名&#xff0c;静态链接库文控以.lib为后缀名。不管是动态链接库还是…

【Mysql】 表的增删查改

文章目录 【Mysql】表的增删查改Create --创建数据Retireve -- 读取数据select 列where条件order by -- 结果排序limit -- 分页 Update -- 更新数据Delete -- 删除数据deletetruncate -- 截断表 插入查询结果聚合函数group by 子句 【Mysql】表的增删查改 CRUD : Create(创建)…

Java开发手册中为什么不建议在for循环中使用“+“进行字符串操作

场景 java开发手册中对于循环体中进行字符串的拼接要求如下&#xff1a; 【推荐】循环体内&#xff0c;字符串的连接方式&#xff0c;使用 StringBuilder 的 append 方法进行扩展。 说明&#xff1a;下例中&#xff0c;反编译出的字节码文件显示每次循环都会 new 出一个 Str…

docker安装golang

最近玩 docker 比较多&#xff0c;试试安装 golang 操作系统&#xff1a;Linux 第一步 先看一下镜像&#xff1a; docker images 看一下我们目前的镜像中&#xff0c;是不是有go 如果有&#xff0c;版本不合适等&#xff0c;可以考虑删除&#xff0c;重新安装&#xff0c;也…

死亡空间2显卡测试软件,《激战2》官方显卡测试数据 A卡略胜N卡

在经过无数次测试后&#xff0c;《激战2》的开发人员从测试玩家处获得了无数的反馈和数据&#xff0c;今天ArenaNet针对硬件配置公布了相关数据&#xff0c;从数据中可以看到&#xff0c;在其他硬件不会成为瓶颈的情况下&#xff0c;AMD显卡帧数要比同等级Nvidia显卡略高&#…

linux运行激战2,在Deepin 20.1系统下可用Wine来模拟运行激战2游戏

经过实测并确定&#xff0c;在Deepin 20.1系统下可以用Wine来模拟运行激战2网络游戏&#xff0c;它的表现跟Windows下差不多&#xff0c;虽然是Wine&#xff0c;但这个游戏优化还是挺好的&#xff0c;我是核显玩的&#xff0c;帧数大概30左右吧&#xff0c;效果在预期之内。 效…

《从零开始的 RPG 游戏制作教程》第六期:设置怪物掉落物并部署关卡怪物

目录 1. 前言 2. 第一期&#xff1a;制作基础场景 3. 第二期&#xff1a;让勇者和怪物登场 4. 第三期&#xff1a;基础的数值设计 5.第四期&#xff1a;从理论的角度简单聊聊关卡 6.第五期&#xff1a;制作物品和技能 第六期&#xff1a;设置怪物掉落物并部署关卡怪物 …

五大移动GPU厂商

《谁能笑傲江湖&#xff1f;移动处理器门派那些事儿》一文中我们把2012年的移动处理器的厂商做了一番介绍&#xff0c;并按照各自的属性给划分了门派。既然把他们称为江湖门派&#xff0c;那么每一个门派总要有自己的绝活。移动处理器厂商中CPU基本都是源自ARM&#xff0c;同架…

趣谈网络协议-第二模块-底层网络知识详解:2最重要的传输层

趣谈网络协议-第二模块-底层网络知识详解:2最重要的传输层 1&#xff1a;第10讲 | UDP协议&#xff1a;因性善而简单&#xff0c;难免碰到“城会玩”TCP 和 UDP 有哪些区别&#xff1f;UDP 包头是什么样的&#xff1f;UDP 的三大特点第一&#xff0c;沟通简单第二&#xff0c;轻…

物联网-鸡舍项目总结

转自&#xff1a;http://mt.sohu.com/20160816/n464326503.shtml&#xff0c;在此向作者致敬&#xff0c;干货很多。 本系统采用五层架构&#xff1a;传感器/智能设备→采集器/智能终端→智能网关→云中间件/Web后台→网页/微信。 鸡舍一般需要监控的参数&#xff0c;包括光照、…

Python爬虫可视化第2季-舌尖上的“小龙虾”

前言&#xff1a; 上期内容与大家分享了一些旅游的内容&#xff0c;从本期开始&#xff0c;会陆续分享一些为吃货们量身定制的文章。世界杯激战正酣&#xff0c;大家在欣赏精彩比赛的同时&#xff0c;怎能少了美食的陪伴&#xff0c;我们今天就来聊聊世界杯的好丽友-小龙虾。 P…

华为的汽车“攻势”

数字化转型&#xff0c;对于传统汽车的从业者而言&#xff0c;看起来还是一个陌生的词汇。\n 然而&#xff0c;现实是&#xff0c;把汽车产品数字化&#xff0c;把企业运营数字化&#xff0c;把一切实体的东西数字化、虚拟化&#xff0c;将成为传统车企不得不直面的事关生死的…

三级pc技术_第十九周PC、笔电、数码周边新品汇总:AMD英特尔激战正酣

【dogkeji-科技犬】 各位网友周末好&#xff0c;又到了2020年第十九周的PC、笔电、数码周边新品发布汇总时刻&#xff08;2020年5月4日至2020年5月9日&#xff09;&#xff0c;那么本周有那些PC、笔电、数码周边新品发布呢&#xff1f;通过科技犬的汇总我们来一起回顾一下吧。 …