进程和环境变量
进程是一个程序执行的上下文集合,这个集合包括程序代码、数据段、堆栈、环境变量、内核标识进程的数据结构等。一个进程可以生成另一个进程,生成的进程称为子进程
,那么相应的就有父进程
,所谓子子孙孙无穷尽也。
子进程
从父进程
处会继承一些遗传因素,其中就包括本文的主题环境变量
。
环境变量是一组特殊的字符型变量,由于具有继承性质,环境变量也经常用于父子进程传递参数用
fork和exec
在unix系统中进程通过依次调用fork()
和exec()
系统调用来实现创建一个子进程。
fork
其实就是克隆
,因为fork()
会复制整个进程,包括进程运行到哪句代码,这意味着新的进程会继续执行fork()
后面的代码,父进程也会运行fork()
后面的代码,从fork()
开始父子进程才分道扬镳。
如果fork返回>0,那么说明在父进程中,如果fork返回==0,说明在子进程中
精确的说exec
是一组函数的统称,并且exec
的准确定义是,用磁盘上的一个新的程序替换当前的进程的正文段、数据段、堆栈段。所以exec并不产生新的进程,而是替换。如此一来进程将从新代码的main开始执行,相当于另外运行了一个完全不同的程序,但保留了原来环境变量。
依据本文的主题,可以把exec
函数分为两类,
一类是可以设置并传递新环境变量的,
一类是不能传递新环境变量的,只能继承原环境变量的。
换句话说,在运行新的程序时,是有机会改变新程序的环境变量的,而不只是继承。
shell
shell并没有什么特殊,也是一个进程,当我们在命令行中敲入一个命令,并且按下Enter
后,shell这个进程会通过fork和exec为我们创建一个子进程(存在一小部分命令不需要启动子进程,称为build-in
命令)并且等待(waitpid)这个子进程完成退出。那么进程的内存镜像显然就包含本文的主题环境变量
set env export 区别
set
其实跟进程创建无关,也跟环境变量无关,它只是当前shell进程内部维护的变量(本地变量),用于变量的引用和展开,不能遗传和继承。
source
执行脚本,意味着fork和exec不会被调用,当前shell直接对test.sh解释执行。这样的话,如果此时test.sh中有export(即putenv),那么将会改变当前shell的环境变量。
env
不是shell的build-in命令,所以shell执行env的时候还是需要创建子进程的