【linux进程(五)】进程间切换以及环境变量问题

简介: 【linux进程(五)】进程间切换以及环境变量问题


1. 前言

掌握了前面文章中

Linux进程相关的内容后,

本篇文章将进行一些实践

包括自制计算器,自己写bash指令等

本章重点:

本篇文章着重讲解Linux是怎样进行
进程间切换的,并且拓展内核2.6版本
的进程运行实例.紧接着讲解main函数
的两个参数以及含义后,自我实现一个
计算器和touch指令,最后讲解环境变量
的基本概念和查看方式!


2. 进程间切换

我们知道一个事实,CPU在调度进程时

并不是一个进程一直在占用CPU资源

它过段时间会被取下来放入其他进程

所以这中间肯定存在进程切换这一过程

两个问题:

  1. 没运行完的进程数据后来去哪儿了?
  2. 当一个进程被取下时
    它在CPU的数据是否会被删除?

第一个问题

很明显,当一个进程在没运行完的
情况下被取下时,肯定会保存一个
信息,那就是当前进程运行到哪儿了?
和C语言的代码相似,当前代码运行
到哪儿了系统是怎么知道的?请看下图:

所以其实在进程运行时,是会使用到

这些寄存器的!进程产生的各种数据

会在寄存器中进行临时保存!

进程在切换时会不断对自己的数据
进行保存(被取下时)和恢复(重新运行时)
当进程进行保存时是保存寄存器中的数据
而不是寄存器本身,并且这些数据会被保存
至一个进程的PCB当中!

第二个问题:

事实上,一个进程被取下来时
CPU并不会删除它的临时数据
而是当下一个进程被放入时,用
下一个进程的数据将上一个进程
的数据覆盖了!


3. Linux2.6内核进程调度队列

注意,这部分是选学,有余力的同学可以看看

请看下图(着重看红框和篮框)

我们着重讲解活跃进程和过期进程的交互!


3.1 活跃进程

首先知道一个事实,Linux中的进程

优先级范围是60~99总共40个等级

其次,运行队列中分活跃进程组和

过期进程组,这个后面再说它们的功能

先来看活跃进程的queue:

CPU在运行时会从上到下扫描队列
若此位置不为空就去运行它指向的PCB
若为空就往后走找优先级最高的进程!


3.2 过期进程

现在有一个问题:当一个优先级为90的
进程正在运行,但是此时突然多了一个优
先级为80的进程,那么这个多加入的进程也
是放入活跃队列中和其中的进程抢占资源吗?

事实上并不会,因为如果有很多优先级很高
的进程不断加入进来,内些原本优先级比较
低的进会迟迟得不到CPU的资源,会进程饥饿!
所以新加入进来的进程会被放进过期队列中!
和活跃进程一样也是按照优先级排列!

它的原理请看下图:

那么当活跃队列中的进程被调度完了

此时CPU是去过期进程调度吗?

答案是不!系统直接使用swap()函数

将活跃进程和过期进程的内容交换
CPU还是在处理活跃队列的进程!


4. main函数参数–命令行参数

main函数其实是有参数的,本篇文章

我只介绍main函数的两个参数

int main(int argc , char* argv[]);
这两个参数又被称为命令行参数
argv是一个数组,指向的元素类型是char*
也就是说argv是一个字符串数组
argc代表这个数组的元素个数!

现在我们并不知道这个数组中

存放的是什么字符串,但是可以写个

代码验证一下,既然知道数组名和元素个数

那么我们就可以通过打印的方式来查看

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

通过下面的视频观察现象:

main


可以发现一个问题:

当我们运行可执行程序a.out时
它会打印0: ./a.out.当我们以空格
为分割在./a.out后面继续输入字符串时
并且输入的是随机字符串,它会以空格
为分割,分别打印出数组中下标为0,1,2
的字符串,这些输出的字符串正是我们输入的!

看下图得出结论:

注:将命令行输入的字符串放入argv数组是OS干的!


5. 利用main函数参数实现简易计算器

既然main函数参数可以读到命令行

中输入的字符串,所以可以用代码实现

一个简易的计算器,代码如下:

#include<stdio.h>    
#include<string.h>    
#include<stdlib.h>    
int main(int argc,char* argv[])    
{    
    if(argc!=4)    
    {    
        printf("%s OP[add|sub|mul|div] d1 d2\n",argv[0]);    
        return 1;    
    }    
    int x=atoi(argv[2]);    
    int y=atoi(argv[3]);    
    if(strcmp(argv[1],"add")==0)    
        printf("%d + %d = %d\n",x,y,x+y);    
    else if(strcmp(argv[1],"sub")==0)    
        printf("%d - %d = %d\n",x,y,x-y);    
    else if(strcmp(argv[1],"mul")==0)    
        printf("%d * %d = %d\n",x,y,x*y);    
    else if(strcmp(argv[1],"div")==0)                                                                                                                                   
        printf("%d / %d = %d\n",x,y,x/y);    
    else    
        printf("输入操作符错误");    
    return 0;    
}

使用方法:

  1. 用户必须先输入可执行程序:a.out
  2. 第二个字符串输入加减乘除其中一个
  3. 第三,第四个字符串输入操作数
  4. 若其中有一个环节输入错误会报提醒


6. 模拟实现Linux中的bash指令

当模拟实现了计算器后,我们隐约可以

发现,其实Linux下的指令如ls,pwd或touch

其实就是调用了不同的可执行程序来完成的!

比如touch指令,输入touch和要创建的文件名
本质就是在C语言程序中创建一个和输入的
文件名一样的文件来间接创建文件

mytouch代码如下:

#include<stdio.h>    
int main(int argc,char* argv[])    
{    
    if(argc != 2)//输入的字符串不规范    
    {    
        printf("touch missing file operand\n");    
        return 1;    
    }    
    FILE* fp = fopen(argv[1],"w");                                                                                                                                      
    if(fp!=NULL)    
        fclose(fp);    
    return 0;    
}

现在我们在Linux下输入指令创建文件:

如果有需要,我们可以自己写一份
可执行程序来模拟Linux下所有的指令!


7. 环境变量PATH初认识

上面所说的内容你可能能理解

就是利用了main函数的参数进行各种运用

但是有几个问题需要解决:

  • 为什么我们自己写的程序运行时要加./
  • 但是系统中的指令:ls,pwd等不用加./?
  • 我们自己写的指令能不能不加./?

我们说执行一个程序的前提是要
找到此程序,我们自己写的程序要
加上./的本质就是让操作系统在当前
目录下寻找我们写的程序,那么为什么
系统中的程序不用加./就能找到呢?

这不得不引出一个概念: 环境变量

保存程序的默认搜索路径的环境变量
叫做: PATH

在运行程序时,系统会去PATH中

找当前可执行程序在不在这些路径中

如果在就直接执行程序,不在就报错

查看环境变量PATH:

使用指令: echo $PATH

这些路径以冒号:为分割

因为我们自己写的程序不在这些路径中

所以我们需要加上./来运行程序!


8. 修改环境变量PATH

要想我们的指令像系统指令一样运行

我们可以将自己写的程序的路径加入

到环境变量PATH中!

使用指令: PATH = $PATH:要添加的路径

此时我已经将我的路径添加到PATH了
现在我直接像系统指令一样运行我的指令:

请注意,当你将你的路径添加后
下次重启时又会恢复为默认路径
所以想一劳永逸的话可以将你自己
的可执行程序放入默认的路径中!


9. 总结

进程的学习需要理论和实践相结合

本篇文章主要是实践部分,而然有两个

问题剖给大家:main函数就只有两个参数吗?

环境变量到底有什么用处?



相关文章
|
6月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
250 67
|
5月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
138 16
|
5月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
108 20
|
4月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
86 0
|
4月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
118 0
|
4月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
84 0
|
4月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
82 0
|
7月前
|
Java Linux 应用服务中间件
在Rocky Linux 9上安装JDK并配置环境变量!
本教程介绍在Rocky Linux 9上安装JDK并配置环境变量的完整步骤。首先更新系统,清理旧版本JDK相关包及残留文件,确保环境干净。接着搜索并安装所需版本的JDK(如OpenJDK 17),验证安装是否成功。然后查找JDK安装路径,配置全局环境变量`JAVA_HOME`和`PATH`,最后验证环境变量设置。按照此流程操作,可顺利完成Java开发环境搭建,支持多版本切换(如JDK 8/11/17)。生产环境请谨慎操作,避免影响现有服务。
1085 21
|
7月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
7月前
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。