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

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:Linux从入门到精通

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学更多操作系统知识

🔝🔝



进程间切换

  • [1. 前言](#1. 前言)
  • [2. 进程间切换](#2. 进程间切换)
  • [3. Linux2.6内核进程调度队列](#3. Linux2.6内核进程调度队列)
    • [3.1 活跃进程](#3.1 活跃进程)
    • [3.2 过期进程](#3.2 过期进程)
  • [4. main函数参数--命令行参数](#4. main函数参数--命令行参数)
  • [5. 利用main函数参数实现简易计算器](#5. 利用main函数参数实现简易计算器)
  • [6. 模拟实现Linux中的bash指令](#6. 模拟实现Linux中的bash指令)
  • [7. 环境变量PATH初认识](#7. 环境变量PATH初认识)
  • [8. 修改环境变量PATH](#8. 修改环境变量PATH)
  • [9. 总结](#9. 总结)

1. 前言

掌握了前面文章中

Linux进程相关的内容后,

本篇文章将进行一些实践

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

本章重点:

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


2. 进程间切换

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

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

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

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

两个问题:

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

第一个问题

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

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

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

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

cpp 复制代码
进程在切换时会不断对自己的数据
进行保存(被取下时)和恢复(重新运行时)
当进程进行保存时是保存寄存器中的数据
而不是寄存器本身,并且这些数据会被保存
至一个进程的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函数的两个参数

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

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

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

代码验证一下,既然知道数组名和元素个数
那么我们就可以通过打印的方式来查看

cpp 复制代码
#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函数参数可以读到命令行

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

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

cpp 复制代码
#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代码如下:

cpp 复制代码
#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函数就只有两个参数吗?

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


相关推荐
火车头-1105 分钟前
【docker 部署nacos1.4.7】
运维·docker·容器
深藏bIue6 分钟前
linux服务器mysql目录下的binlog文件删除
linux·服务器·mysql
虾..23 分钟前
Linux 进程状态
linux·运维·服务器
测试者家园24 分钟前
DevOps 到底改变了测试什么?
运维·自动化测试·软件测试·devops·持续测试·智能化测试·软件测试和开发
扛枪的书生1 小时前
Linux 通用软件包 AppImage 打包详解
linux
只想安静的写会代码1 小时前
网卡信息查询、配置、常见故障排查
linux·服务器·windows
jiayong232 小时前
多子系统架构下的Nginx部署策略与最佳实践
运维·nginx·系统架构
皮糖小王子2 小时前
Docker打开本地镜像
运维·docker·容器
wavemap2 小时前
阿里云38元一年200M轻量云服务器详细评测
服务器·阿里云·云计算·vps·评测·boboforum
偶像你挑的噻4 小时前
9-Linux驱动开发-设备树=>设备树插件实现 RGB 灯驱动
linux·驱动开发·stm32·嵌入式硬件