exec
exec 函数族的作用是执行参数所指定的可执行文件或脚本。这个函数会替换掉当前进
程的内存镜像,也就是执行这个函数成功后,调用该函数的程序就不存在了,像是移
花接木一样。Linux下的的 exec 并不是一个函数,而是一族函数,一共有如下几个函
数,原型为:
1 | int execve(const char *filename, char *const argv[], |
这 7 个函数中只有execve()
是真正的系统调用函数,其它几个最终都会调用它。
exec 后面的字母的含义为:
字母 | 助记 | 含义 |
---|---|---|
l | list | 参数逐个列举 |
v | vector | 用向量(字符串数组)传递参数 |
p | path (I guess~) | 从$PATH 中查找可执行文件 |
e | environment | 设置环境变量 |
Special semantics for execlp() and execvp()
The execlp(), execvp(), and execvpe() functions duplicate the actions of
the shell in searching for an executable file if the specified filename
does not contain a slash (/) character. The file is sought in the
colon-separated list of directory pathnames specified in the PATH
environment variable. If this variable isn’t defined, the path list
defaults to the current directory followed by the list of directories
returned by confstr(_CS_PATH). (This confstr(3) call typically returns
the value “/bin:/usr/bin”.)
意思是:如果指定的文件名不包含/
的话,execlp()`
execvp()execvpe()
会重
复 shell 查找可执行文件的行为(即从环境变量
PATH所指定的目录中寻找文件)。
如果变量
PATH没有设置,会使用当前目录加上
confstr(_CS_PATH, …)`的输出作
为目录集并从中寻找可执行文件。
当目录里没有/
且没有设置PATH
时,man exec
中说会将当前目录加入查找可执行
文件的目录集,但我测试似乎并没有当前目录,也可能是我理解错了。测试代码如下:
1 |
|
命令如下:
1 | $ clang execlp.c -o execlp |
全都提示找不到文件。以下是一些例子。
例子 1
先写一个辅助程序,打印出程序执行的一些信息(argv 和 envp):
1 | /* |
由于环境变量太多,这时只打印出前 5 个。下面是execve()
的一个例子:
1 | /* execve.c */ |
execve()
执行成功是不会返回的,只有在失败的时候会返回-1
,并设置相应的errno
。在我电脑上的执行结果为:
1 | $ clang argv.c -o argv |
例子 2
还有一个例子:
1 | /* execve_pid.c */ |
执行结果为:
1 | $ clang execve_pid.c -o execve_pid |
可以看到执行了execve()
后进程 ID 没有变化,可知原进程被替换了。而且在指定
了envp
参数时,进程不再继承 shell 的环境变量。
References
- Linux 手册:
man exec
,man execve
,man confstr
- Linux进程控制——exec函数族