当前位置: 首页 > news >正文

Linux 进程优先级、程序地址空间、进程控制

个人主页:仍有未知等待探索-CSDN博客

专题分栏: Linux

目录

一、进程优先级

1、什么是进程优先级?

2、为什么要有优先级?

3、Linux的优先级特点、查看方式

4、命令行参数和环境变量

1.命令行参数

2.环境变量

获取环境变量的方式:

二、程序地址空间

1、进程的地址空间

2、基本理解

对于现象的解释(操作系统 -> 写时拷贝):

3、细节问题

为什么不在子进程创建的时候就直接全部拷贝一份?

4、如何理解地址空间

1.区域的划分

2.地址空间的理解

3.为什么要有地址空间

4.页表和写时拷贝的理解

5.虚拟地址的理解

6.Linux中调度

大O(1)调度算法

三、进程控制

1、进程创建

进程调度fork之后,内核的工作(步骤)

进程具有独立性的理解

fork函数的返回值

fork函数为什么会有两次返回值

fork函数常规用法

fork函数调用失败的原因

写时拷贝

2、进程终止

进程终止的意义

进程终止的三种情况

进程为什么会异常?

进程退出的原因?

进程退出判断顺序?

如何终止?

3、进程等待

进程等待是什么?

进程等待的原因

wait/waitpid

status参数是什么?

退出信息

如何理解阻塞等待子进程?

如何从status中获取到退出码和退出信息?

非阻塞等待

4、进程的程序替换

exec系列函数

解释原理

进程替换有没有创建新的进程?

怎么加载?

exec*系列的返回值

程序替换的意义

系统调用:execve


一、进程优先级

1、什么是进程优先级?

进程获取某种资源(cpu)的先后顺序。

  • task_struct 进程控制块 -> int prio;
  • Linux中优先级数字越小,优先级越高
  • 优先级和权限的区别:优先级是能执行,表示执行的顺序;而权限是能不能执行的问题。

2、为什么要有优先级?

进程访问cpu的资源始终是有限的

操作系统关于调度和有限级的原则:分时操作系统:根据时间片来进行调度 --- 保证基本的公平。

如果进程长时间不被调度,就造成了饥饿问题。

3、Linux的优先级特点、查看方式

  • Linux查看优先级的指令:ps -al
  • PRI:进程的优先级,NI:进程优先级的修正数据(用于对优先级的动态修改)。最终进程的优先级 = PRI + NI。
  • 调整优先级的指令:top --->  r ---> PID to renice -> Value(本人修改的NI值)NI值也就是nice值,不是随便调整的,而是有范围的[-20, 19]
  • 每次优先级的调整,PRI的值都是从80开始的。

4、命令行参数和环境变量

1.命令行参数

int main(int argc, char *argv[]):对于这种写法的main函数里面的参数代表着什么

是命令行字符串,程序的路径+名称 和 该进程匹配的选项。

命令行参数的意义

命令行参数的本质是交给我们不同的选项,来定制不同的程序功能

  • 父进程的数据默认能被子进程看到并访问。

  • 命令行中启动的程序,都会变成进程,都是bash的子进程。

2.环境变量

Linux中存在一些全局的设置,告诉命令行解释器,应该去哪个路径下去寻找可执行程序。

  • 可以用env指令去查看所有的环境变量:

  • 可以用echo指令打印环境变量的内容:

  • 默认我们能查到的环境变量是内存级别的,当xshell重启后,环境变量默认会恢复。
  • 环境变量不是在内存中,而是在系统对应的配置文件中。内存的环境变量,是xshell启动的时候,加载到内存中的。
  • env:一个查看环境变量的指令

    export name=value:导入环境变量的指令

    unset name:取消环境变量的指令

  • 本地变量:hello=1234,不能被子进程继承。这个helloc是本地变量,当你用env查看环境变量的时候是不会找到这个变量的。

  • environ -> 一个char**类型,存放着环境变量(unistd.h、需要声明,extern char** environ)
  • 环境变量可以被子进程拿到的。-> 环境变量默认在bash内部。

  • bash进程启动的时候,默认会给子进程形成两种表:

    argv[]命令行参数表、env[]环境变量表。bash通过各种方式交给子进程。

  • 环境变量具有系统级的全局属性,因为环境变量本身会被子进程继承下去。

  • echo、export都是内建命令(不是bash子进程创建的,而是bash执行的)。

  • 本地变量旨在本bash内部有效,无法被子进程继承下去,导成环境变量,此时才能够被获取。

获取环境变量的方式:

1、函数:获取环境变量的值:char* getenv(char* name)。

2、extern char** environ。

3、通过main函数的参数。

二、程序地址空间

1、进程的地址空间

现象:在一段代码中,子进程改变了全局变量,但是在父进程中读取到的仍是原来的值,并且子进程和父进程中全局变量的地址一样。

2、基本理解

  • 每个进程都有一个独立的地址空间。
  • 每个进程都有一个独立的页表。
  • 地址空间的本质就是内核中的一个结构体对象。
  • 子进程会把父进程的大部分内核数据拷贝一份。

对于现象的解释(操作系统 -> 写时拷贝):

如果子进程要修改的值,这个值不仅仅只有子进程在使用的话,操作系统会重新开辟一块新的物理空间,将数据拷贝给新的物理空间,让子进程指向新的物理空间(修改物理内存、修改页表)。(物理内存中的代码和数据要拷贝一份、task_struct也要拷贝一份,拷贝后的内容大部分和之前是相同的)

子进程和父进程中共享变量的地址相同,其实是虚拟地址相同而已。

3、细节问题

如果父子进程不写的话,全局变量默认是被父子共享的,代码是共享的(只读)。

为什么不在子进程创建的时候就直接全部拷贝一份?

为了节省空间。并且父子进程共享的数据中,有大部分数据都是不会进行修改的 --- 按需申请。

4、如何理解地址空间

1.区域的划分

地址空间本质是内核的一个struct结构体,很多的属性都是表示范围的变量(start,end)

struct area
{int start;int end;
}

2.地址空间的理解

地址空间是一个结构体,有各种的地址划分。

如下图,

3.为什么要有地址空间

实际的物理空间,代码区、数据区、堆区、栈区、共享区、命令行参数和环境变量都是乱序的。

所以为了好管理,人为的规定了地址空间。

  • 地址空间将无序变成有序,让进程以统一的视角看待物理内存以及自己运行的各个区域。

  • 进程管理模块和内存管理模块进行解耦。

  • 拦截非法请求。

4.页表和写时拷贝的理解

5.虚拟地址的理解

程序运行后,使用的是虚拟空间的地址,而想要得到物理地址需要用页表进行映射。

最开始的时候,地址空间和页表中的数据是由操作系统在程序加载到内存中动态创建和管理的。

6.Linux中调度

在Linux中,每个cpu都会由一个运行队列。

大O(1)调度算法

三、进程控制

1、进程创建

进程调度fork之后,内核的工作(步骤)

  1. 分配新的内存块和内核数据结构给子进程。

  2. 将父进程大部分数据结构内容拷贝至子进程。

  3. 添加子进程到系统进程列表中。

  4. fork返回,开始调度器调度。

进程具有独立性的理解

子进程有自己的相关管理数据结构,虽然代码是和父进程共享的,但是数据被写时是以写时拷贝进行独立的。

fork函数的返回值

子进程返回0,父进程返回子进程的pid。

fork函数为什么会有两次返回值

在fork函数返回之前,子进程已经创建完毕,可以开始进行调度了。

fork函数常规用法

1、子进程复制父进程,是父子进程同时执行不同的代码段。

2、子进程执行一个不同的程序。

fork函数调用失败的原因

1、系统中有太多的进程。

2、实际用户的进程数超过了限制。

写时拷贝

2、进程终止

进程终止的意义

1、释放曾经的代码和数据所占用的空间。

2、释放内核数据块。 --- 可能延迟释放。(僵尸状态)

进程终止的三种情况

1、代码跑完,结果正确。

2、代码跑完,结果不正确。

2、代码执行时,出现了异常,提前退出了。

  • 结果正不正确可以通过进程的退出码决定
  • 一旦出现异常,退出码就没有任何的意义了。

pl:在用VS编程时,代码运行的时候崩溃了。 --- 本质就是os发现这个进程做了不该做的事情(如:访问了非法地址等),直接杀死了进程。

进程为什么会异常?

进程出现异常 本质上 就是因为进程收到了os发给进程的信号!

我们可以通过查看退出信号来判断进程出现异常的情况。

进程退出的原因?

可以根据退出码来进行判断,退出的原因。

进程退出判断顺序?

1、先看退出信息,判断是否是因为异常而退出的。

2、如果不是异常引起的,在看退出码,判断是否运行正常。

衡量一个进程退出,只需要退出码和退出信号

如何终止?

1、main函数中return,表示进程结束。(非main函数中return,表示函数结束)

2、调用exit函数。注意:我们代码的任意位置调用exit(int status),都表示进程退出。

3、调用_exit(int status) --- 系统调用。

3、进程等待

进程等待是什么?

任何进程在退出的情况下,一般必须要被父进程进行等待。如果父进程不管不顾,子进程变成Z状态,内存泄漏。

进程等待的原因

  • 父进程通过等待解决子进程退出的僵尸问题,回收系统资源。(一定要考虑)
  • 获取子进程退出的信息。(不一定需要)

wait/waitpid

status参数是什么?

  • 输出型参数
  • 输出子进程退出信息。

退出信息

退出信息 = 进程退出码 + 退出信号

一个int,在X86下是32位bit位,怎么存储信息如下:

如何理解阻塞等待子进程?

阻塞等待子进程的本质是父进程主动放弃CPU使用权,进入等待状态,并将其PCB从运行队列转移到等待队列中。当子进程结束时,父进程会被操作系统唤醒并重新加入到运行队列中。

如何从status中获取到退出码和退出信息?

1、退出码 = (status >> 8) & 0xFF

     退出信号 = status & 0x7F

2、WIFEXITED(status) --- 判断是不是正常退出(判断退出信号)。

      WEXITSTATUS(status) --- 获取子进程退出码。

非阻塞等待

  • waitpid的参数optionsu如果为0就是阻塞等待,如果为WNOHANG就是非阻塞等待。

  • waitpid采用非阻塞等待,本质就是检测子进程的状态变化。

pid_t > 0:  调用成功了,并且子进程退出了,父进程回收成功。

pid_t < 0:  调用失败了。

pid_t == 0:调用是成功的,只不过子进程还没退出,需要要你下一次进行重复等待。

  • 非阻塞等待的时候 + 循环 = 非阻塞轮询。

4、进程的程序替换

exec系列函数

就是用exec系列的函数,执行新的程序。

解释原理

进程替换有没有创建新的进程?

没有创建新进程。只是把新程序的代码和数据覆盖老进程。页表可能会修改一下新的映射关系,PCB属性可能会有改变。

站在被替换进程的角度,本质就是这个程序被加载到内存了!

怎么加载?

exec*系列函数类似于是一种Linux上的加载函数。

exec* 系列的函数,执行完毕之后,后续的代码不见了,被替换了。

exec*系列的返回值

exec* 函数的返回值不需要考虑,如果exec*函数运行成功了,后续代码不会被运行;如果运行失败了,才会运行后续代码。

程序替换的意义

创建子进程,让子进程完成任务:

1、让子进程执行父进程代码的一部分

2、让子进程执行一个全新的程序。

系统调用:execve

谢谢大家!!! 

相关文章:

Linux 进程优先级、程序地址空间、进程控制

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a; Linux 目录 一、进程优先级 1、什么是进程优先级&#xff1f; 2、为什么要有优先级&#xff1f; 3、Linux的优先级特点、查看方式 4、命令行参数和环境变量 1.命令行参数 2.环境变量 获取环境变量的…...

学习笔记一

vector 在创建时指定初始大小和初始值&#xff1a; vector<int> a(5, 1) // 包含 5 个整数的 vector&#xff0c;每个值都为 1 可以使用 push_back 方法向 vector 中添加元素&#xff1a; a.push_back(7) // 将整数 7 添加到 vector 的末尾 可以使用 size(…...

Linux中信号的发送及信号的自定义捕捉方法

预备知识&#xff1a; 信号产生时进程早已知道该信号如何处理。 信号产生时进程可能并不能立即处理信号而是等到合适的时候处理。 信号其他相关常见概念 实际执行信号的处理动作称为信号递达(Delivery) 信号从产生到递达之间的状态,称为信号未决(Pending)。 进程可以选择阻…...

yum仓库的制作与使用

目录 前言&#xff1a; 1 查看系统内核 2 获取网络源 3 搭建yum网络仓库 4 rpm包的下载 4.1 将rpm包下载至本地 4.2 对下载的rpm包进行备份 5 制作本地yum源 5.1 软件仓库制作工具createrepo 5.2 使用createrepo创建本地yum仓库 6 搭建docker本地仓库 前言&#x…...

牛客周赛54:D.清楚姐姐跳格子(bfs)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 \,\,\,\,\,\,\,\,\,\,老妪遂递一羊皮卷轴&#xff0c;上面什么都没有&#xff0c;清楚欲问&#xff0c;老妪却缄口不言。           \,\,\,\,\,\,\,\,\,\,清楚性格刚直&…...

用户空间 lmkd

用户空间 lmkd 1、概览1.1 配置lmkd 2、lmkd2.1 lmkd启动2.2 时序图 Android LowMemoryKiller原理分析 AOSP>文档>核心主题低内>存终止守护程序 1、概览 Android Low Memory Killer Daemon &#xff1a;system/memory/lmkd/README.md Android 低内存终止守护程序 (lm…...

二叉树专题

Leetcode 104. 二叉树的最大深度 class Solution { public:int maxDepth(TreeNode* root) {if(!root) return 0;int leftd maxDepth(root -> left) 1;int rightd maxDepth(root -> right) 1;return max(leftd, rightd);} }; Leetcode 100. 相同的树 class Solution…...

Spring MVC 之简介及常见注解

一、什么是 Spring MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从一开始就包含在 Spring 框架中。它的正式名称 “Spring Web MVC” 来自其源模块的名称 (Spring-webmvc)&#xff0c;但它通常被称为"Spring MVC"。 什么是Servlet呢? S…...

除了使用本地存储,还有哪些方法可以实现只出现一次的弹窗?

除了使用本地存储&#xff0c;还有以下几种方法可以实现只出现一次的弹窗&#xff1a; 1.使用 Cookie&#xff1a;可以将一个标识符存储在浏览器 Cookie 中&#xff0c;下次用户访问页面时检查 Cookie 中是否存在该标识符&#xff0c;从而判断是否需要显示弹窗。 2.使用服务器端…...

微软蓝屏事件揭示的网络安全深层问题与未来应对策略

目录 微软蓝屏事件揭示的网络安全深层问题与未来应对策略 一、事件背景 二、事件影响 2.1、跨行业连锁反应 2.2、经济损失和社会混乱 三、揭示的网络安全问题 3.2、软件更新管理与风险评估 3.2、系统复杂性与依赖关系 3.3、网络安全意识与培训 四、未来的网络安全方向…...

C#:通用方法总结—第11集

大家好&#xff0c;今天继续分享我们的通用方法系列。 下面是今天要分享的通用方法&#xff1a; &#xff08;1&#xff09;这个通用方法为Ug’校验选中体的个数&#xff1a; /// <summary> /// 输出选中体个数 /// </summary> public int CheckOneBody() { int …...

Web开发-html篇-下

这篇是接着上篇的内容&#xff0c;接着介绍html的其他标签及属性的用法&#xff0c;感兴趣的可以从我的html上篇看起 1. 超链接示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport&…...

【C++从小白到大牛】多态那些事儿(上)

一、多态的概念 1.1概念: 通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 二、 多态的定义及实现 2.1多态的构成条件 多态是在不同继承关系的类对象&#xff0c;去调用同一函数&#xff0c;产…...

网站在线查询工具箱源码分享

终极网络工具系统”(SAAS)&#xff0c;是一款功能强大的PHP脚本在线查询工具。本版集合了超过470种快速且易用的Web工具&#xff0c;为日常任务处理和开发人员提供了极大的便利。作为一款综合性的网络工具系统&#xff0c;66toolkit不仅满足了用户的基本网络需求&#xff0c;更…...

SSH简写且免密登陆终端设备

问题 通常使用ssh连接远程设备时&#xff0c;需要先执行ssh <username><ip>&#xff0c;然后再输入终端设备的用户密码。比较麻烦。 解决 可以用如下方法设置命令缩写以及免密登陆&#xff1a; 免密 首先在本地生成私钥&#xff1a; ssh-keygen -t rsa # or …...

算力共享中神经网络切片和算力分配策略

目录 神经网络切片 按照算力的分布进行网络层数切片;就是算力越强,运算神经网络层数越多 神经网络切片和算力占比进行映射 算力分配策略 get_current_shard 神经网络切片 按照算力的分布进行网络层数切片;就是算力越强,运算神经网络层数越多 神经网络切片和算力占比进…...

3章4节:R的逻辑运算和矩阵运算

逻辑运算和矩阵运算是R语言中两个重要的功能模块,前者用于逻辑判断和条件筛选,后者用于处理多维数据结构和执行线性代数运算。本文章详细介绍R语言中的逻辑运算和矩阵运算,帮助读者掌握这两类运算的基本概念、操作方法和实际应用。 一、逻辑运算 逻辑运算在编程语言中扮演着…...

使用EasyAR打包安卓操作注意

EasyAR for Scene 4.6.3 丨Unity2020.3.15f2 打包Unity注意事项 一、默认渲染管线 官方参考链接&#xff1a;ARFoundation 简单注意 1.打包设置为Android平台 2.PackageName和EasyAR中保持一致 3.Scripting Backend设置为IL2CPP&#xff0c;以及设置为ARM64 4.取消Auto …...

驾驭PyCharm:破解环境配置的迷宫

驾驭PyCharm&#xff1a;破解环境配置的迷宫 PyCharm&#xff0c;作为Python开发者的首选IDE之一&#xff0c;以其强大的功能和用户友好的界面而广受好评。然而&#xff0c;即便是最强大的工具&#xff0c;环境配置问题也可能成为开发者的拦路虎。本文将带你深入探索PyCharm中…...

大数据技术原理-Hadoop的安装

摘要 随着大数据时代的到来&#xff0c;Hadoop作为一项重要的分布式计算框架&#xff0c;其安装与配置是大数据技术学习者必须掌握的技能。本文通过实验报告的形式&#xff0c;详细记录了在虚拟机环境下安装Hadoop并配置其为伪分布式模式的全过程。实验过程中&#xff0c;遇到…...

从根儿上学习spring 八 之run方法启动第四段(2)

图2 我们接着上一篇接着来看refresh方法&#xff0c;我们上一小节说完了invokeBeanFactoryPostProcessors(beanFactory)方法&#xff0c;这一节我们来看registerBeanPostProcessors(beanFactory)方法。 从方法名称定义我们就能看出这个方法主要是用来注册BeanPostProcesor的。…...

牛顿插值法代替泰勒公式

引入 例题 近似函数&#xff1a; 通过这个近似函数可以看出&#xff0c;若要证的函数超过二阶可导&#xff0c;那么就不适合用牛顿插值法代替泰勒公式 因为&#xff0c;后面的操作非常复杂&#xff0c;不划算了… 总结 我们可以通过牛顿插值法生成一个逼近曲线的直线&#xf…...

为 Laravel 提供生产模式下的容器化环境:打造现代开发环境的终极指南

为 Laravel 提供生产模式下的容器化环境&#xff1a;打造现代开发环境的终极指南 在现代开发中&#xff0c;容器化已经成为一种趋势。使用 Docker 可以让我们轻松地管理和部署应用程序。本文将带你一步步构建一个高效的 Laravel 容器化环境&#xff0c;确保你的应用程序在开发…...

Visual Studio 和 VSCode 哪个好?

​ 您好&#xff0c;我是程序员小羊&#xff01; 前言 想要对Visual Studio 和 VSCode 进行比较&#xff0c;就要充分了解Visual Studio (VS) 和 Visual Studio Code (VSCode) 各有其优势和适用场景进行分析。Visual Studio (VS) 和 Visual Studio Code (VSCode) 都是由微软开发…...

百款精选的HTML5小游戏源码,你可以下载并直接运行在你的小程序或者自己的网站上

今天我带来了一份特别的礼物——百款精选的HTML5小游戏源码&#xff0c;你可以下载并直接运行在你的小程序或者自己的网站上&#xff0c;只需双击index.html即可开始。无论你是在寻找创意引流&#xff0c;还是想为你的网站增添互动性&#xff0c;这些小游戏都能帮你实现&#x…...

01 LVS负载均衡群集

集群 在互联网应用中&#xff0c;随着站点对硬件的性能、响应速度、服务稳定性、数据可靠性等要求越来越高&#xff0c;单台服务器越来越力不从心 集群的含义 Cluster&#xff0c;集群也叫群集由多台主机构成&#xff0c;但对外只表现为一个整体 集群分类 类型 负载均衡集…...

Redis结合Lua脚本的简单使用

我们就拿购物车举例子 现在有5个东西免费送&#xff0c;我们只能选择1个 例如 可乐 美年达 香蕉 苹果 薯片 我们选择后就放进redis里面 然后我们不能选重复&#xff0c;只能选不同 Lua脚本 我们redis使用lua脚本的时候&#xff0c;会传两个参数进去 一个是List<Strin…...

Java使用zip4j加密压缩和解压文件与文件夹

最近项目中有个需求需要对文件夹进行压缩后传输&#xff0c;考虑数据泄露安全性问题&#xff0c;需要对压缩包进行加密&#xff0c;特地查找了下开源压缩加密类库&#xff0c;找到了Java语言开发的zip4j库&#xff0c;觉得挺好用的&#xff0c;在这分享给大家&#xff01; Jav…...

一款好用的开源网站内容管理系统

今天给大家介绍的是一款开源网站内容管理系统&#xff08;灵活、易用&#xff0c;性能良好、运行稳定&#xff0c;轻松管理建设网站&#xff09; 官网&#xff1a;https://www.ujcms.com/ 介绍 客户端兼容Edge&#xff08;Chromium版&#xff09;、谷歌浏览器&#xff08;Chro…...

Qt Modbus 寄存器读写实例

一.线圈状态寄存器读写 项目效果如下 1. 写单个寄存器 MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); int addrui->spinBoxwirte_addr->value();int dataui->spinBoxwirte_data->value();int ret modbus_write_bit(mb,addr,d…...