Linux:进程优先级与命令行参数

目录

1.进程优先级

1.1 基本概念

1.2 查看系统进程

1.3 修改进程优先级的命令

2.进程间切换

2.1 相关概念

2.2 Linux2.6内核进程调度队列(了解即可)

3.命令行参数


1.进程优先级

1.1 基本概念

  1. cpu资源分配的先后顺序,就是指进程的优先权(priority)。
  2. 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  3. 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。 

我们知道进程在内存中是需要排队的,比如运行队列,等待队列。那排队是干什么的:就是在确认优先级,来确定得到某种资源的先后顺序。为什么要确认优先级,本质就是资源不足。那么操作系统是怎么做到呢?我们下面讲解:

优先级其实就是PCB中的一个 int 字段数值越小,优先级越大,跟我们的考试排名一样。Linux进程的优先级数值范围:60~99。Linux中默认进程的优先级都是80。

1.2 查看系统进程

我们先编写一段代码

在linux或者unix系统中,用ps -la 命令则会类似输出以下几个内容:

我们很容易注意到其中的几个重要信息,有下:

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  • NI :代表这个进程的nice值

PRI and NI:

PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高

那NI就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值

PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为PRI(new)=PRI(old)+nice。pri(old) ,都是从80开始的!

这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值

nice其取值范围是-20至19,一共40个级别。nice调整最小是:-20,超过部分统一当成-20。nice调整最大是:19,超过部分统一当成19。


PRI vs NI:

  • 需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正修正数据

1.3 修改进程优先级的命令

用top命令更改已存在进程的nice:

  • top
  • 进入top后按“r”–>输入进程PID–>输入nice值

我们输入进程号讲 nice 改为19

普通用户是没有办法将优先级调大,让PRI减小的。需要使用su换成root,或使用sudo命令。 

2.进程间切换

2.1 相关概念

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

因为要并发,所以必定要考虑进程间切换。

每一个进程不是占有CPU就一直运行,每隔一段时间,会自动被操作系统从cpu上剥离下来。Linux内核是支持进程之间进行cpu资源抢占的!是基于时间片的轮转式抢占式内核。

为什么我们函数内定义的栈临时变量,会返回给外部,我们的程序/进程,它怎么知道我们当前运行到哪里里?如何做到函数间跳转? 因为cpu内存在大量寄存器,比如eip是程序计数器或者叫pc,会自动执行我们要执行的下一行代码。我们的进程在运行的时候,是会使用这些寄存器的,我们的进程,会产生各种数据,在寄存器中临时保存。

如果我们有多个进程呢?各个进程在CPU寄存器中形成的临时数据,都应该是不一样的!而cpu内寄存器只有一套,我们如何做到让每个进程使用cpu时能从上次时间片执行到的位置继续执行?我们可以先简单的理解为时间片结束后,cpu寄存器中的数据会先保存到进程PCB中,然后下次执行时先读取PCB中存储的寄存器的数据,然后继续执行,本质就是将CPU寄存器的内容,保存到内存中!

2.2 Linux2.6内核进程调度队列(了解即可)

上图是Linux2.6内核中进程队列的数据结构,之间关系也已经给大家画出来,方便大家理解

一个CPU拥有一个runqueue

  • 如果有多个CPU就要考虑进程个数的负载均衡问题

优先级

  • 普通优先级:100~139(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)
  • 实时优先级:0~99(我们这里不关心)

活动队列

  • 时间片还没有结束的所有进程都按照优先级放在该队列
  • nr_active: 总共有多少个运行状态的进程
  • queue[140]: 一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!
  • 从该结构中,选择一个最合适的进程,过程是怎么的呢?

1. 从0下表开始遍历queue[140]
2. 找到第一个非空队列,该队列必定为优先级最高的队列
3. 拿到选中队列的第一个进程,开始运行,调度完成!
4. 遍历queue[140]时间复杂度是常数!但还是太低效了!

  • bitmap[5]:一共140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用 5*32 个比特位表示队列是否为空,即位段,这样,便可以大大提高查找效率!

过期队列

  • 过期队列和活动队列结构一模一样
  • 过期队列上放置的进程,都是时间片耗尽的进程,或者是刚到运行对列中的进程。
  • 当活动队列上的进程都被处理完毕之后,对过期队列的进程进行时间片重新计算

active指针和expired指针

  • active指针永远指向活动队列
  • expired指针永远指向过期队列
  • 可是活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间片到期时一直都存在的。
  • 没关系,在合适的时候,只要能够交换active指针和expired指针的内容,就相当于有具有了一批新的活动进程!

总结

在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法

3.命令行参数

 命令行参数是什么?

我们看下面一段代码看下面一段代码

#include <stdio.h>    
#include <string.h>    
#include <stdlib.h>    
int main(int argc, char *argv[])    
{    int i = 0;for(;i<argc;i++){printf("%d: %s\n",i, argv[i]);}printf("hello world\n");return 0;
}

运行输出: 

可以发现main函数是可以传参的,shell 会自动讲命令行输入的一大串字符,按空格分割成小的字串,第一参数argc存命令行字串个数,第二个参数argc是一个指针数组存字串内容。

命令行参数,可以支持各种指令级别的命令行选项的设置!这样就可以理解之前学的指令,选项是什么关系了。

我们来模拟实现一个计算器

#include <stdio.h>    
#include <string.h>    
#include <stdlib.h>    
int main(int argc, char *argv[])    
{    if(argc != 4)      {      printf("Use error\nUsage: %s op[-add|sub|mul|div] d1 d2\n",argv[0]);      return 1;      }      // 你的程序一定有4个命令行参数,第一个是程序名      int x = atoi(argv[2]);      int y = atoi(argv[3]);      if(strcmp(argv[1],"-add")==0)      {      int result = x+y;      printf("%d+%d=%d\n",x,y,result);      }      else if(strcmp(argv[1],"-sub")==0)      {      int result = x-y;      printf("%d-%d=%d\n",x,y,result);      }      else if(strcmp(argv[1],"-mul")==0)      {      int result = x*y;      printf("%d*%d=%d\n",x,y,result);                                                                                                       }  else if(strcmp(argv[1],"-div")==0)      {      if(0==y)      {printf("%d/%d=error! div zero\n",x,y);}else {int result = x/y;printf("%d/%d=%d\n",x,y,result);}}else {printf("Use error,you should use the right command line\nUsage: %s op[-add|sub|mul|div] d1 d2\n",argv[0]);}return 0;
}

 运行结果:

对于为什么系统命令不用加 ./指定位置 ,而我们写的程序就需要写 ./ ,这就涉及到环境变量了,下一篇文章我们讲解环境变量。

本篇结束!

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

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

相关文章

利用Node.js和cpolar实现远程访问,无需公网IP和路由器设置的完美解决方案

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

LeetCode 77.组合

题目&#xff1a; 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 方法&#xff1a;灵神-组合型回溯 剪枝 class Solution {private int k;private final List<Integer> path new ArrayList<>();…

反序列化 [网鼎杯 2020 朱雀组]phpweb 1

打开题目 我们发现这个页面一直在不断的刷新 我们bp抓包一下看看 我们发现index.php用post方式传了两个参数上去&#xff0c;func和p 我们需要猜测func和p两个参数之间的关系&#xff0c;可以用php函数MD5测一下看看 我们在响应处得到了一串密文&#xff0c;md5解密一下看看 发…

Windows11安装使用Oracle21C详细步骤<图文保姆级>新版本

Windows11安装使用Oracle21C详细步骤<图文保姆级>新版本 Database Software Downloads | Oracle 中国 下载完成后解压缩 双击setup.exe 打开安装页面 同意下一步 更改自己的路径点击下一步 输入密码 下一步安装等待即可 等待加载配置时间有点久 完成即可 使用 搜索…

【Kubernetes】四层代理Service

Service四层代理 一、Service概念原理1.1、为什么要有Service1.2、Service概述1.3、工作原理1.4、三类IP地址【1】Node Network&#xff08;节点网络&#xff09;【2】Pod network&#xff08;pod 网络&#xff09;【3】Cluster Network&#xff08;服务网络&#xff09; 二、S…

C++之异常处理

C语言传统的处理错误的方式 传统的错误处理机制&#xff1a; 1. 终止程序, 如assert. 缺陷: 用户难以接受, 如发生内存错误, 除0错误时就会终止程序. 如果assert括号里面的表达式结果为假, 那么assert就会中断程序并报错, 所以使用assert可以帮助我们在程序判断一些可能出错的…

翻转二叉树(图解、前序遍历、递归与非递归)

LCR 144. 翻转二叉树 - 力扣&#xff08;LeetCode&#xff09; 给定一棵二叉树的根节点 root&#xff0c;请左右翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [5,7,9,8,3,2,4] 输出&#xff1a;[5,9,7,4,2,3,8] 提示&#xff1a; …

【11】Qt Designer

目录 VSCode添加外部工具 QtDesigner PyUIC PyRCC 加载UI文件模板代码 QMainWindow QWidget 常用知识点 1. 修改标题图标 2. 图片资源管理 3. 图片按钮 4. 加载对话框 5. 动态加载Widget 6. 修改主题 其他注意事项 事件被多次触发 PyQt5提供了一个可视化图形工…

【小沐学Python】Python实现WebUI网页图表(gradio)

文章目录 1、简介2、安装3、基本测试3.1 入门代码3.2 组件属性3.3 多个输入和输出组件3.4 图像示例3.5 聊天机器人3.6 模块&#xff1a;更灵活、更可控3.7 进度条 结语 1、简介 https://www.gradio.app/ Gradio是用友好的网络界面演示机器学习模型的最快方法&#xff0c;因此…

【T+】畅捷通T+软件安装过程中停留在:正在配置产品位置或进度80%位置。

【问题描述】 畅捷通T软件在安装过程中&#xff0c; 进度条一直停留在【正在配置产品…】位置。 【解决方法】 打开【任务管理器】&#xff0c;想必这个如何打开&#xff0c;大家应该都会。 在【进程】中找到【DBConfig.exe】或者【Ufida.T.Tool.SM.DBConfig.exe】进程并结束…

Linux 基础IO

文章目录 前言基础IO定义系统IO接口文件描述符重定向原理缓冲区刷新 前言 要知道每个函数/接口的全部参数和返回值建议去官网或者直接在Linux的man手册中查&#xff0c;这不是复制粘贴函数用法的文章。 C语言文件读写介绍链接 基础IO定义 IO是Input/Output的缩写&#xff0c…

optional

参考资料&#xff1a; Java8 Optional用法和最佳实践 - 掘金 一、背景 根据Oracle文档&#xff0c;Optional是一个容器对象&#xff0c;可以包含也可以不包含非null值。Optional在Java 8中引入&#xff0c;目的是解决 NullPointerExceptions的问题。本质上&#xff0c;Optio…

2024年网络安全竞赛-网站渗透

网站渗透 (一)拓扑图 1.使用渗透机对服务器信息收集,并将服务器中网站服务端口号作为flag提交; 使用nmap工具对靶机进行信息收集 2.使用渗透机对服务器信息收集,将网站的名称作为flag提交; 访问页面即可 3.使用渗透机对服务器渗透,将可渗透页面的名称作为flag提交…

软件测试:测试用例八大要素模板

一、通用测试用例八要素 1、用例编号&#xff1b; 2、测试项目&#xff1b; 3、测试标题&#xff1b; 4、重要级别&#xff1b; 5、预置条件&#xff1b; 6、测试输入&#xff1b; 7、操作步骤&#xff1b; 8、预期输出 二、具体分析通用测试用例八要素 1、用例编号 一般是数字…

[NAND Flash 2.1] NAND Flash 闪存改变了现代生活

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< ​ 1989年NAND闪存面世了&#xff0c;它曾经且正在改变了我们的日常生活。 NAND 闪存发明之所以伟大&#xff0c;是因为&#xff0c…

苹果OS X系统介绍(Mac OS --> Mac OS X --> OS X --> macOS)

文章目录 OS X系统介绍历史与版本架构内核与低级系统图形&#xff0c;媒体和用户界面应用程序和服务 特性用户友好强大的命令行安全性集成与互操作性 总结 OS X系统介绍 OS X是由苹果公司为Macintosh计算机系列设计的基于UNIX的操作系统。其界面友好&#xff0c;易于使用&…

Servlet学习笔记

简介 浏览器请求处理流程&#xff1a;浏览器发请求 > 服务器tomcat( > 应用程序 ( > servlet) ) Servlet应用的三大作用域&#xff1a;request&#xff0c;session&#xff0c;application tomcat存放项目的层级结构 注释&#xff1a;servlet原引用包名 javax.serv…

Git的安装以及SSH配置

前言 近期工作需要&#xff0c;所以版本管理工具要用到Git&#xff0c;某些操作需要ssh进行操作&#xff0c;在某次操作中遇到&#xff1a;git bash报错&#xff1a;Permission denied, please try again。经排查是ssh没有配置我的key&#xff0c;所以就借着这篇文章整理了一下…

WorkPlus即时通讯,让沟通零障碍!企业协作更高效

如今&#xff0c;随着信息技术的快速发展&#xff0c;企业对于高效沟通和即时协作的需求也日益增长。在这个数字化时代&#xff0c;WorkPlus作为一款领先的企业级移动办公平台&#xff0c;以其强大的即时通讯功能和卓越的用户体验&#xff0c;成功为企业打造了高效沟通的新时代…

input = torch.randn(20, 2, 11, 11, 32)输出形式

input torch.randn(20, 2, 11, 11, 32) m torch.nn.AdaptiveAvgPool3d((1,1, 32)) xm(input) print(x.shape) 结果&#xff1a; 也就是不用管批次和通道数