exec
第一次发现有exec这个功能。从网上摘抄了一些功能如下。
exec是 Shell 内置命令,它有两种用法,一种是执行 Shell 命令,一种是操作文件描述符。
资源
操作文件描述符
使用 exec 命令可以永久性地重定向,后续命令的输入输出方向也被确定了,直到再次遇到 exec 命令才会改变重定向的方向;换句话说,一次重定向,永久有效。
示例:
能将标准输出的内容,重定向到文件log.txt,而终端无输出。
# 进行重定向,后续的命令输出都会受该命令影响。
exec >log.txt
echo "hello world jkj"
echo "zhang jia kou"
echo "su chuan chao"
exec >&2
echo "重定向已恢复"
说明:
exec >log.txt,它等价于exec 1>log.txt,将当前 Shell 进程的所有标准输出重定向到 log.txt 文件。后面的两个 echo 命令都没有在显示器上输出,而是输出到了 log.txt 文件。
exec >&2,它等价于exec 1>&2,用来恢复重定向,让标准输出重新回到显示器。2 是标准错误输出的文件描述符,它也是输出到显示器,并且没有遭到破坏,我们用 2 来覆盖 1,就能修复 1,让 1 重新指向显示器。
重定向的恢复
方法1:
/dev/tty 文件代表的就是显示器,将标准输出重定向到 /dev/tty 即可,也就是 exec >/dev/tty。
方法2:
如果还有别的文件描述符指向了显示器,那么也可以别的文件描述符来恢复标号为 1 的文件描述符,例如 exec >&2。注意,如果文件描述符 2 也被重定向了,那么这种方式就无效了。
执行Shell命令
下面一大段我也没有搞明白是什么意思,反正exec执行后,后续的代码就不会再执行了。
- 系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。
一个进程主要包括以下几个方面的内容:
(1)一个可以执行的程序
(2) 与进程相关联的全部数据(包括变量,内存,缓冲区)
(3)程序上下文(程序计数器PC,保存程序执行的位置)
- exec是一个函数簇,由6个函数组成,分别是以excl和execv打头的。
执行exec系统调用,一般都是这样,用fork()函数新建立一个进程,然后让进程去执行exec调用。我们知道,在fork()建立新进程之后,父进各与子进程共享代码段,但数据空间是分开的,但父进程会把自己数据空间的内容copy到子进程中去,还有上下文也会copy到子进程中去。而为了提高效率,采用一种写时copy的策略,即创建子进程的时候,并不copy父进程的地址空间,父子进程拥有共同的地址空间,只有当子进程需要写入数据时(如向缓冲区写入数据),这时候会复制地址空间,复制缓冲区到子进程中去。从而父子进程拥有独立的地址空间。而对于fork()之后执行exec后,这种策略能够很好的提高效率,如果一开始就copy,那么exec之后,子进程的数据会被放弃,被新的进程所代替。
- exec与system的区别
(1) exec是直接用新的进程去代替原来的程序运行,运行完毕之后不回到原先的程序中去。
(2) system是调用shell执行你的命令,system=fork+exec+waitpid,执行完毕之后,回到原先的程序中去。继续执行下面的部分。
总之,如果你用exec调用,首先应该fork一个新的进程,然后exec. 而system不需要你fork新进程,已经封装好了。