Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。
CPU执行进程时分为两种模式:1. 并发 2. 并行.
并行是当有多个CPU时,每个进程都可以物理意义上的同时运行
并发是指每一个进程在一定的时间内轮流的使用CPU,是逻辑上的同时运行
一定的时间我们称之为时间片.每个进程在时间片结束后,需要离开CPU.这一过程我们称为进程切换(进程切换基于时间片轮转的调度算法)
所以我们在C++里写一个死循环并不会让整个电脑瘫痪.
那么刚刚CPU下次怎么知道自己上次执行到了哪里?难道每一次都要从头开始执行嘛?
在CPU中有许多寄存器,他们帮助CPU提高效率.
我们先来简单的理解下寄存器是什么?
我们之前介绍过函数栈帧.那么一个函数结束之后,他的局部变量不是被销毁了嘛?为什么可以传到函数外面去.
在销毁之前,将其存到了CPU的寄存器当中.所以外部程序可以通过寄存器来接收到已经销毁的局部变量的值.
所以寄存器的作用为:将进程中的高频数据存入寄存器中,以提高CPU的工作效率
CPU中有一个叫做eip的寄存器,永远指向运行指令的下一条.所以CPU执行当前语句之后会知道自己接下来要执行什么语句.
那么回答最开始的问题.CPU如何知道当下要运行的这个进程上一次执行到哪里了?
进程的TASK_STRUCT中有一个专门维护CPU信息的结构体,要从CPU中下来的时候,会用这个结构体去保存CPU中关于运行的相关信息(例如EIP当前指向的位置就会被保存下来).
这个词如果在WINDOWS中配置过Python等语言一定听说过,其中最折磨的部分就是修改系统环境变量
在Linux中同样有这么一个概念.我们先来看看接下来这个现象
#include
int main()
{
printf("hello environment!\n");
return 0;
}
这是一段简单的程序.我们一样先编译再运行
gcc -o proce proce.cpp && ./proce
在屏幕上打印出了"hello environment!"
那我们如果返回到上一个目录中,输入./mycode还能运行吗?显然是不能的,我们需要输入完整的路径.例如我这里是**./8.4/mycode**
才可以运行
那为什么我们输入系统中的ls指令或其他指令时不需要这样输入路径然后运行呢?
因为系统中会自己去已经存在的路径中寻找.这个路径存在环境变量中.(可以理解为这个系统环境中的全局变量)
echo $PATH
我们可以在屏幕上打印出当前的环境变量
我们可以把自己上面写的程序路径加入到PATH当中就可以直接输入了
PATH=$PATH:你的程序绝对路径
我们在命令行中输入env,就可以查看当前所有的环境变量
可以看到很多有意思的变量.
BASH: 当前使用的命令行解释器的路径
PWD:当前工作路径
HOME:家目录.(每次我们登录服务器时,系统会先判断你为什么用户,然后执行cd 环境变量中对应的目录,就是我们开机的样子)
我们可以看出,其为一个key-value的结构.
在代码中我们可以使用getenv来获取想要的环境变量值.
man getenv
其在3号手册中,为库函数.返回值为获取的变量值.
我们简单来试一下
#include
int main()
{
printf("PATH:%s",getenv("PATH"));
return 0;
}
这就是使用它的方法.
我们通常写的main函数是长这个样子的
int main()
他是没有参数的
我们也可以将他写成这个样子
int main(int argc,char * argv[],char* env[])
这是两张核心向量表!
argc:传入的argv参数数量
argv:命令行参数,其中第一个为当前可执行程序的名称,之后为传入的参数.以NULL结尾
env:当前进程中的环境变量.以NULL结尾
我们可以写一个这样的程序来获取我们输入的命令行参数
#include
int main(int argc,char* argv[])
{
for(int i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
return 0;
}
因为main函数也是被启动的函数,启动其的函数会向其传递该参数表.以此来为指令,工具,软件等提供命令行选项的支持.
我们也可以通过同样的方式来获取环境变量
#include
int main(int argc,char* argv[],char* env[])
{
for(int i=0;env[i];i++)
{
printf("%s\n",env[i]);
}
return 0;
}
我们还可以通过extern char **environ来获取
#include
int main(int argc,char* argv[],char* env[])
{
extern char **environ;
int i = 0;
for(; environ[i]; i++)
{
printf("%d: %s\n", i, environ[i]);
}
return 0;
}
本地变量只能在本bash中,并不会被创建的子进程所继承.类似于局部变量,而环境变量相当于全局变量
之前我们提到过BASH只负责解释命令,而执行命令是通过创建子进程来完成的.这部分我们称为常规命令
而有一部分命令是BASH自己去执行的
例如cd(若创建子进程去切换目录,最终切换的是子进程的工作空间,并不会改变当前进程)
我们可以使用如下的方式验证下echo是内建命令还是常规命令
var=1000
echo $var
前面我们提到过,var为本地变量,只能在当前进程使用.若echo出来了var的值,则说明BASH没有创建子进程去执行echo这条指令
而有一部分命令是BASH自己去执行的
例如cd(若创建子进程去切换目录,最终切换的是子进程的工作空间,并不会改变当前进程)
我们可以使用如下的方式验证下echo是内建命令还是常规命令
var=1000
echo $var
前面我们提到过,var为本地变量,只能在当前进程使用.若echo出来了var的值,则说明BASH没有创建子进程去执行echo这条指令