并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。
我们知道一个进程在cpu上执行了一段时间之后,即使没有执行完,也会被剥离下来,我们把这称为基于进程切换基于时间片轮转的调度算法。
1.为什么函数的返回值会被外部拿到呢?
答:返回的时候会保存到寄存器里,通过CPU的寄存器拿到数据。
当返回的数据很大时,会用多个寄存器保存。
2.系统如何得知代码执行到第几行了?
答:通过程序计数器pc(也叫eip)
程序计数器:记录当前进程正在执行指令的下一行指令的地址。
其实CPU中有很多寄存器,例如通用寄存器(eax,ebx),记录栈帧的(ebp,esp,eip),状态寄存器(status);
那么这些寄存器都有什么作用呢?
答:提高效率,进程高频数据会放入寄存器中;也就是说,CPU内的寄存器保存的是,进程相关的数据,而这些数据被称为上下文。
进程在从CPU上离开的时候,要将自己的上下文数据保存好,甚至带走,其目的是为了下次运行此进程时能够恢复,否则每次都从头开始运行,效率太低了。
上下文会存在进程的PCB中。
进程切换时:
在初学C语言的时候,可能在一些书籍上会看到main函数带参数,就像这样
int main(int argc,char*argv[])
{
//....
return 0;
}
这个argv是一个整型,argc表示argv指针数组的大小。
那这些参数有什么用呢?
我们知道其实代码在执行时,第一个调用的函数不是main函数,所以是可以给main函数传参的
在来看下面这一段代码:
#include <stdio.h>
int main(int argc,char*argv[])
{
for(int i=0;argv[i];i++)
{
printf("argv[%d]->%s\n",i,argv[i]);
}
return 0;
}
运行结果:
其实 "./mycmd -a -b -c -d" 被当成一个字符串,以空格为分隔,被分成了五个字符串,然后再依次填入argv指针数组中,最后一个位置的下一个位置再填成空指针。
那么这有什么用呢?
我们平常使用的那些指令,例如 ls 什么的,它们后面跟不同的选项,就会有不同的功能,原理就是这个命令行参数。
例:
int main(int argc,char*argv[])
{
if(argc==2)
{
if(strcmp(argv[1],"-a")==0)
printf("功能1\n");
else if(strcmp(argv[1],"-b")==0)
printf("功能2\n");
else if(strcmp(argv[1],"-c")==0)
printf("功能3\n");
else if(strcmp(argv[1],"-d")==0)
printf("功能4\n");
else
printf("default\n");
}
else
printf("mycmd -> [-a|-b|-c|-d]\n");
return 0;
}
环境变量是系统提供的一组name=value形式的变量,不同的环境变量有不用的用途,通常具有全局性和可继承性。
我们所运行的进程,都是bash的子进程,bash本身在启动的时候,会从操作系统的配置文件中读取相关环境变量的信息,子进程会继承父进程交给我的环境变量。
下面让我们来认识几个环境变量
PATH : 指定命令的搜索路径
我们在使用ls这些命令时,并不需要带路径,而使用我们自己写的就要带路径,这是为什么呢?
这就跟PATH环境变量有关了。
使用下面命令,查看PATH环境变量
echo $PATH //$符号用于提取环境变量的值,否则只是单纯的打印PATH
可以看到,这一串用 " : " 分隔开的路径,就是系统寻找命令的路径,我们可以把当前路径添加进PATH,这样我们自己写的也可以不带路径直接使用了。
不过这个PATH是内存性质的,如果不小心改错了,也不用担心,重新登陆 xshell 就行了。
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
echo $HOME
SHELL : 当前Shell,它的值通常是/bin/bash
echo $SHELL
NAME=value //像这样设置的就是本地变量,注意 = 号两边不能有空格
本地变量只在bash本地有效,不可以被继承。
环境变量的组织方式和命令行参数是一样的。
所以一个进程在运行时,不是简单的加载到内存中,还会传入两张核心向量表:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("PATH:%s\n",getenv("PATH"));
return 0;
}
其实main函数还能传第三个参数:char *env[]
#include <stdio.h>
int main(int argc, char* argv[], char* env[])
{
for (int i = 0; env[i]; i++)
{
printf("env[%d]->%s\n", i, env[i]);
}
return 0;
}
由于很长,这里只截一部分
#include <stdio.h>
int main()
{
extern char**environ; //注意要先声明一下
for(int i=0;environ[i];i++)
{
printf("environ[%d]->%s\n",i,environ[i]);
}
return 0;
}
这里发生了一个奇怪的现象,MY_VALUE是本地变量,为什么可以用echo命令打印出来?
执行命令时,bash要创建子进程,那么它运行的时候要创建子进程吗?
如果需要创建子进程,那么因为本地变量不会被继承,也就不会被打印出来,可事实并非如此。
其实命令分为两批:
而echo就是一个典型的内建命令,类似的还有 cd 命令。