一)概述:
- exec函数允许将一个可执行程序进程的控制转移到另一个可执行程序的进程上。
- exec调用并没有生成新的进程,而是在原有进程的基础上,替换原有进程的正文,调用前后是同一个进程,进程的PID不变。
- 在Linux中并没有名为exec的函数,它们只有一个系统调用:execve.库提供的所有函数只有这个系统调用的封装。
- execve系统调用可以查找指定的文件,这里主要有三种可执行文件,第一是可执行脚本,第二是可执行目标文件,第三是二进制文件。
二)脚本中fork/exec/source之间的区别:
通过以下的脚本对这三种方式进行说明:
more test1.sh test2.sh
::::::::::::::
test1.sh
::::::::::::::
#!/bin/bash
var1=“OLD_VALUE”
export var1
echo “PID for test1.sh before exec/source/fork:$$”
echo “test.sh: \$var1 is $var1”
case $1 in
exec)
echo “using exec.。.”
exec 。/test2.sh
;;
source)
echo “using source.。.”
source 。/test2.sh
;;
*)
echo “using fork.。.”
。/test2.sh
esac
echo -e “\n\rPID for test1.sh after exec/source/fork;$$”
echo “test1.sh \$var1 is $var1”
::::::::::::::
test2.sh
::::::::::::::
#!/bin/bash
echo -e “\r\nPID for test2.sh; $$”
echo “test2.sh get \$var1=$var1 from test2.sh”
var1=“NEW_VALUE”
export var1
echo “test2.sh: \$var1 is $var1”
脚本说明:
运行脚本test1.sh,此时var1=“OLD_VALUE”,并且export var1,随后根据argv[1]中的内容,通过exec,fork或者source调用test2.sh
脚本中使用fork运行test2.sh的运行结果:
。/test1.sh fork
PID for test1.sh before exec/source/fork:12248
test.sh: $var1 is OLD_VALUE
using fork.。.
PID for test2.sh; 12249
test2.sh get $var1=OLD_VALUE from test2.sh
test2.sh: $var1 is NEW_VALUE
PID for test1.sh after exec/source/fork;12248
test1.sh $var1 is OLD_VALUE
解析:
使用 fork 方式运行 script 时, 就是让 shell(parent process) 产生一个 childprocess 去执行该 script,
当 child process 结束后, 会返回 parent process,但 parent process 的环境是不会因 child process 的改变而改变的。
通过返回结果我们看到脚本加载test2.sh后,派生出新的进程(test2.sh12249),test2.sh继承了test1.sh的环境变量var1=OLD_VALUE,
同时修改了var1=NEW_VALUE,而父进程(test1.sh/12248)的var1未被修改,依然是OLD_VALUE.
脚本中使用source运行test2.sh的运行结果:
。/test1.sh source
PID for test1.sh before exec/source/fork:12254
test.sh: $var1 is OLD_VALUE
using source.。.
PID for test2.sh; 12254
test2.sh get $var1=OLD_VALUE from test2.sh
test2.sh: $var1 is NEW_VALUE
PID for test1.sh after exec/source/fork;12254
test1.sh $var1 is NEW_VALUE
解析:
使用 source 方式运行 script 时, 就是让 script 在当前 process 内执行, 而不是产生一个 child process 来执行.