【Linux】从零开始认识进程 — 中下篇

news2024/10/7 10:19:48

在这里插入图片描述
送给大家一句话:
人一切的痛苦,本质上都是对自己无能的愤怒。而自律,恰恰是解决人生痛苦的根本途径。—— 王小波

从零认识进程

  • 1 进程优先级
    • 1.1 什么是优先级
    • 1.2 为什么要有优先级
    • 1.3 Linux优先级的特点 && 查看方式
    • 1.4 其他概念
  • 2 命令行参数
  • 3 环境变量
    • 3.1 什么是环境变量
    • 3.2 见见更多的环境变量
    • 3.3 整体理解
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

今天我们继续学习Linux的进程,上两篇文章我们认识了什么是进程,如何创建进程,进程状态。今天我们主要讲解 进程优先级和环境变量。

1 进程优先级

学习优先级需要了解:

  1. 什么是优先级
  2. 为什么要有优先级
  3. Linux优先级的特点 && 查看方式

1.1 什么是优先级

  • cpu资源分配的先后顺序,就是指进程的优先权(priority)。
  • 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能
    其实很简单,就是指定进程的获取资源的先后顺序(在运行队列中的相对顺序)。
    在task_struct模块中的内部字段 存在 int prio = ??,优先级的本质是一个数字,数字越小,优先级越高

1.2 为什么要有优先级

因为CPU的资源是有限的,不得不排队(就像食堂打饭一样),系统大部分情况进程是比较多的,但是硬件只有一套。

操作系统关于的调度好优先级的原则:分时操作系统,基本的公平。如果进程因为长时间不被调度,就造成的饥饿问题。
我们来简单查看一下进程的优先级:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main()
  5 {
  6   while(1){
  7     printf("I am a process , pid: %d\n",getpid());                                 
  8     sleep(1);
  9   }
 10 }
 11 

这里介绍一下一个新指令: ps -l
在这里插入图片描述
运行是运行了,但是没有我们现在的进程,这是因为ps -l默认是显示当前终端的进程,我们使用ps -al就可以查看全部的了。
在这里插入图片描述
其中:

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :代表这个进程是由哪个进程发展衍生而来的,即父进程的PID
  • PRI : 进程优先级
  • NI : 进程优先级的修正数据,nice值,新的优先级 = 优先级 + nice值,达到对进程优先级的动态化处理(每次调用都可以更新nice值)

通过上图,可以看到我们进程(pid : 6000)的优先级是80。

1.3 Linux优先级的特点 && 查看方式

接下来我们来看如何查看修改优先级
用top命令更改已存在进程的nice:
进入top后按 r 输入进程PID –> 输入nice值,就可以修改nice值。来进行一下尝试:
在这里插入图片描述
可以看到,我们想要改到100,但是最终结果是99,这是为什么???
nice值不能随意调整,而是有范围的 [-20 , 19)共四十个数字(即四十 个 梯度)
我们通过ps-al查看的进程信息中,nice值就是最大值 19。
每次调整完优先级都是从80开始的,通过 新的优先级 = 优先级(80) + nice值进行计算。
注意:作为普通用户不能频繁调整优先级 想要多次调整需要root身份。

同时调整优先级也可以使用nicerenice命令,具体使用方法可以用那个男人 man 来进行查看(以renice 为例):

RENICE(1)                           User Commands                          RENICE(1)

NAME
       renice - alter priority of running processes

SYNOPSIS
       renice [-n] priority [-gpu] identifier...

DESCRIPTION
       renice  alters the scheduling priority of one or more running processes.  The
       first argument is the priority value to be used.   The  other  arguments  are
       interpreted as process IDs (by default), process group IDs, user IDs, or user
       names.  renice'ing a process group causes all processes in the process  group
       to have their scheduling priority altered.  renice'ing a user causes all pro‐
       cesses owned by the user to have their scheduling priority altered.
OPTIONS
       -n, --priority priority
              Specify the scheduling priority to be used for  the  process,  process
              group,  or  user.  Use of the option -n or --priority is optional, but
              when used it must be the first argument.

       -g, --pgrp pgid...
              Force the succeeding arguments to be interpreted as process group IDs.

       -u, --user name_or_uid...
              Force the succeeding arguments to be interpreted as usernames or UIDs.

       -p, --pid pid...
              Force the succeeding arguments to be interpreted as process  IDs  (the
              default).

       -h, --help
              Display a help text.

       -V, --version
              Display version information.


也就是使用 renice -n ? -p ?就可以完成修改优先级。

1.4 其他概念

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

2 命令行参数

命令行参数其实很简单,我们已经用过许多次了。类似 rm -f grep -v 等等都是命令行参数。那么这本质到底是什么呢???

我们先从main函数讲起,我们都知道main函数有参数int main( int argc, char* argv[ ]),(但实际我们经常不带,今天不管这个问题)
下面我们来看具体是什么作用:

    1 #include<stdio.h>
    2 #include<unistd.h>
    3 
W>  4 int main(int argc , char* argv[])//这里的报错先忽视
    5 {
    6   for(int i = 0; i < argc ;i++ )
    7   {
    8     printf("argv[%d]-> %s\n",i,argv[i]);                                         
    9   }
   10   return 0;
   11 }                                                            
   12  

来看运行效果:
在这里插入图片描述
实际上main函数的参数就是命令行的参数,也就是命令行字符串。前面的./myprocess是程序的路径和名称,后面的-a -b -c -d就是该进程匹配的选项。
那为什么要这么干呢???又是谁干的呢???
来看下面一段代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 
  5 int main(int argc , char* argv[])
  6 {
  7   if(argc != 2)
  8   {
  9     printf("Usage:%s -[a,b,c,d]\n",argv[0]);
 10     return 1;
 11   }
 12 
 13   if(strcmp(argv[1],"-a") == 0)
 14   {
 15     printf("this is function1\n");
 16   }
 17 
 18   else if(strcmp(argv[1],"-b") == 0)
 19   {
 20     printf("this is function2\n");
 21   }
 22 
 23   else if(strcmp(argv[1],"-c") == 0)
 24   {
 25     printf("this is function3\n");
 26   }
 27 
 28   else if(strcmp(argv[1],"-d") == 0)
 29   {
 30     printf("this is function1\n");
 31   }                               
 32   else
 33   {
 34     printf("no this function!!!\n");
 35   }                                                                                
 36   return 0;                        
 37 }                                  
 38  

这样可以区分命令行输入了哪些信息,并执行相应功能。来看效果:

laik
为什么要有命令行参数???
本质:命令行参数的本质是交给我们不同程序的不同选项,用来定制不同功能,一般命令里会带许多选项

这样通过不同选项就执行程序的不同功能。这是不是有点像我们经常使用的哪些命令呢!?ll ls rm -f等等
那这个工作时是谁来干的呢???
我们进行一个小小的测试:

    1 #include<stdio.h>
    2 #include<unistd.h>
    3 #include<string.h>
    4 
    5 int g_val = 10000;
    6 
W>  7 int main(int argc , char* argv[])    
	8 {    
	9   printf("I am father process,pid : %d ,ppid: %d ,g_val: %d\n",getpid(),getppid(),g_val);
   10   sleep(5);
   11   
   12   pid_t id = fork();
   13   if(id == 0)
   14   {
   15     //child
   16     while(1)
   17     {
   18       printf("I am child process,pid: %d,ppid: %d,g_val: %d\n",getpid(),getppid(),g_val);
   19       sleep(1);   
   20     }
   21   }   
   22   else   
   23   {
   24     //father
   25        
   26       printf("I am father process,pid: %d,ppid: %d,g_val: %d\n",getpid(),getppid(),g_val);                                                                        
   27       sleep(1);                       
   28   }                                   
   29                                       
   30   return 0;                           
   31 }

来看效果:
在这里插入图片描述
可以看到子进程和父进程都成功使用了g_val,即父进程的数据默认可以被子进程看到并访问!!!
而其中的PID:10069是谁呢???
命令行中的程序都会变成进程,其实都是bash 的子进程!!!
所以那这个工作时是谁来干的呢???都是bash进行的,也就是main函数的参数是bash处理的

3 环境变量

3.1 什么是环境变量

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
  • 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

系统中的很多配置,在我们登录Linux就已经被加载到bash进程中了。
来看一个(搜索路径的环境变量):
在这里插入图片描述
bash在执行命令的时候,需要先找到命令,因为未来要加载!!!
同样只要我们把我们写可执行程序拷贝到对应路径就可以不用再写./就可以执行。
当然这样太粗暴了,我们可以使用PATH = 路径这样就改变我们的环境变量了:
在这里插入图片描述

但是现在我们好多指令都不能正常使用了???啊???怎么办???原来的路径不一致,寻找不到了大部分指令。
这时候重启即可。
在这里插入图片描述
这样就恢复了,但是到底怎样才能把我们的程序路径加入进PATH呢???
应该使用PATH=$PATH : 路径即可。
在这里插入图片描述
这样就成功加入了!!!

注意 最开始的环境变量不是在内存中,而是在系统的对应的配置文件中
那配置文件在哪里呢???就在家目录的几个文件中
在这里插入图片描述

3.2 见见更多的环境变量

环境变量都是大写的英文字母,使用echo $名字即可
使用env就可以查看所有的环境变量:
在这里插入图片描述
这些都是环境变量!!!我们来认识其中几个:

  1. HOME:这个代表登录默认所处路径,即家目录
  2. PWD:这个会动态储存我们所在的目录
  3. SHELL:这个会默认启动命令行解释器,让我们可以输入命令
  4. HISTSIZE:这个是指历史命令的个数,意义是历史命令最多有多少条(一般是1000条)

等等都是环境变量
当然自己也可以定义环境变量。
使用export就可以进行:export THIS_IS_MY_ENV = hellobit这样就创建一个环境变量!!!
如果不加export 就会创建本地变量,与环境变量不同(需要对通信,多线程有一定了解才能理解)。

3.3 整体理解

    1 #include<stdio.h>
    2 #include<unistd.h>
    3 #include<string.h>
    4 
    5 int g_val = 10000;
    6 
    7 int main()
    8 {
    9   extern char** environ;
   10   for(int i = 0;environ[i];i++)
   11   {
   12     printf("env[%d]->%s\n",i,environ[i]);                                                                                                                                   
   13   }                                                                                                                                      
   14   return 0;                                                                                                                              
   15 }         

在这里插入图片描述
这样我们就通过C语言程序成功获取了环境变量。
然后因为我们的程序是一个进程,是bash的子进程,所以环境变量可以被子进程获取!!!
(环境变量在BASH中)

首先数据储存在磁盘中,运行时会加载到内存中,也就把环境变量存入内存中的bash/shell.
bash进程在启动的时候,默认会给子进程形成两张表:

  1. argv[ ] :命令行参数。
  2. env[ ] : 环境变量表,通过各种方式交给子进程。

环境变量具有系统级的全局属性,因为会被子进程继承下去!!!
esport , echo 等是内建命令,由bash执行,80%命令是bash创建的子进程实行

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

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

相关文章

1.6.1 变换

我们要想改变物体的位置&#xff0c;现有解决办法是&#xff0c;每一帧改变物体的顶点并且重配置缓冲区从而使物体移动&#xff0c;但是这样太繁琐&#xff0c;更好的解决方式是使用矩阵&#xff08;Matrix&#xff09;来更好的变换&#xff08;Transform&#xff09;一个物体。…

Python更改Word文档的页面大小

页面大小确定文档中每个页面的尺寸和布局。在某些情况下&#xff0c;您可能需要自定义页面大小以满足特定要求。在这种情况下&#xff0c;Python可以帮助您。通过利用Python&#xff0c;您可以自动化更改Word文档中页面大小的过程&#xff0c;节省时间和精力。本文将介绍如何使…

每日一题 --- 删除链表的倒数第 N 个结点[力扣][Go]

删除链表的倒数第 N 个结点 题目&#xff1a;19. 删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#x…

Python中lambda函数使用方法

在Python中&#xff0c;lambda 关键字用于创建匿名函数&#xff08;无名函数&#xff09;&#xff0c;这些函数的特点是简洁、一次性使用&#xff0c;并且通常用于只需要一行表达式的简单场景。下面是lambda函数的基本结构和使用方法&#xff1a; 基本语法&#xff1a; lambd…

代码随想录算法训练营DAY7| C++哈希表Part.2|LeetCode:454.四数相加II、383.赎金信、15. 三数之和、18.四数之和

文章目录 454.四数相加II思路C代码 383.赎金信C 代码 15. 三数之和排序哈希法思路C代码 排序双指针法思路去重C代码 18.四数之和前言剪枝C代码 454.四数相加II 力扣题目链接 文章链接&#xff1a;454.四数相加II 视频链接&#xff1a;学透哈希表&#xff0c;map使用有技巧&…

STL的基本概念

一、STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 面向对象的三大特性(简单理解) 封装&#xff1a;把属性和行为抽象出来作为一个整体来实现事和物 继承&#xff1a;子类继承父类&a…

linux下docker容器的使用

1、根据已有镜像images创建容器 1.1、查看镜像 如果是接手的别人的项目&#xff0c;需要从以往的images镜像中创建新容器&#xff0c;使用命令查看当前机器上的docker镜像&#xff1a; docker images1.2、创建容器 使用docker run 根据images镜像名创建容器&#xff0c;命令…

电阻的妙用:限流、分压、滤波,助力电路设计!

电阻可以降低电压&#xff0c;这是通过电阻的分压来实现的。事实上&#xff0c;利用电阻来降低电压只是电阻的多种功能之一。电路中的电阻与其他元件&#xff08;电容、电感&#xff09;结合用于限流、滤波等。&#xff08;本文素材来源&#xff1a;https://www.icdhs.com/news…

SV-7045V网络草坪音箱 室外网络广播POE供电石头音箱

SV-7045V网络草坪音箱 室外网络广播POE供电石头音箱 描述 IP网络广播草坪音箱 SV-7045V是深圳锐科达电子有限公司的一款防水网络草坪音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到功率20W。用在公园&#…

Kotlin高效App爬取工具:利用HttpClient与代理服务器的技巧

在当今数字化时代&#xff0c;移动应用&#xff08;App&#xff09;数据的价值日益凸显&#xff0c;而为了获取并分析这些数据&#xff0c;开发高效的数据爬取工具变得至关重要。Kotlin作为一种现代化、功能强大的编程语言&#xff0c;与HttpClient等强大工具的结合&#xff0c…

day53 动态规划part10

121. 买卖股票的最佳时机 简单 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可…

蓝桥杯学习笔记 单词分析

试题 G: 单词分析 时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分 [问题描述] 小蓝正在学习一门神奇的语言&#xff0c;这门语言中的单词都是由小写英文字母组成&#xff0c;有些单词很长&#xff0c;远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词&#xf…

C语言实现顺序表(增,删,改,查)

目录 一.概念&#xff1a; 1.静态顺序表&#xff1a;使用定长数组存储元素。 2.动态顺序表&#xff1a;使用动态开辟的数组存储。 二.顺序表的实现: 1.顺序表增加元素 1.检查顺序表 2.头插 3.尾插 2.顺序表删除元素 1.头删 2.尾删 3.指定位置删 3.顺序表查找元素 …

就业班 第二阶段 2401--3.25 day5 mycat读写分离

[TOC] 启动并更改临时密码 [rootmysql1~]# systemctl start mysqld && passwdgrep password /var/log/mysqld.log | awk END{ print $NF} && mysqladmin -p"$passwd" password Qwer123..; MyCAT读写分离 Mycat 是一个开源的数据库系统&#xff0c;但…

线程安全集合类原理

一、ConcurrentHashMap (一)、HashMap 1、JDK7 并发死链 采用头插法 扩容源码(扩容时并没有创建新的节点&#xff0c;只是将引用挂在不同的地方) void transfer(Entry[] newTable, boolean rehash) {int newCapacity newTable.length;for (Entry<K,V> e : table) {…

俚语加密漫谈

俚语加密是一种古老而有效的通信方式&#xff0c;将特定词语或短语在群体内赋予特殊含义&#xff0c;从而隐藏真实信息。类似于方言&#xff0c;它在历史上的应用不可忽视。随着计算机时代的到来&#xff0c;现代密码学通过数学运算编织密语&#xff0c;使得加密变得更加高深莫…

大数据开发(离线实时音乐数仓)

大数据开发&#xff08;离线实时音乐数仓&#xff09; 一、数据库与ER建模1、数据库三范式2、ER实体关系模型 二、数据仓库与维度建模1、数据仓库&#xff08;Data Warehouse、DW、DWH&#xff09;1、关系型数据库很难将这些数据转换成企业真正需要的决策信息&#xff0c;原因如…

【Java多线程】1——多线程知识回顾

1 多线程知识回顾 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记仓库&#x1f449;https://github.com/A-BigTree/tree-learning-notes 个人主页&#x1f449;https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star…

web 技术中前端和后端交互过程

1、客户端服务器交互过程 客户端:上网过程中,负责浏览资源的电脑,叫客户端服务器:在因特网中,负责存放和对外提供资源的电脑叫服务器 服务器的本质: 就是一台电脑,只不过相比个人电脑它的性能高很多,个人电脑中可以通过安装浏览器的形式,访问服务器对外提供的各种资源。 个人…

【每日一题】2580. 统计将重叠区间合并成组的方案数-2024.3.27

题目&#xff1a; 2580. 统计将重叠区间合并成组的方案数 给你一个二维整数数组 ranges &#xff0c;其中 ranges[i] [starti, endi] 表示 starti 到 endi 之间&#xff08;包括二者&#xff09;的所有整数都包含在第 i 个区间中。 你需要将 ranges 分成 两个 组&#xff0…