实例解析shell子进程(subshell )
通过实例,解析个人对shell子进程的一个了解,主要包括以下几个方面
1:什么是shell子进程
2:shell什么情况下会产生子进程
3:子进程的特点与注意事项
4:$变量$$在脚本里的意义,及如何得到子进程里的进程号
参考文档:apue,bash的man和info文档
1:什么是shell子进程
子进程,是从父子进程的概念出发的,unix操作系统的进程从init进程开始(init进程为1,而进程号0为系统原始进程,以下讨论的进程原则上不包括进程0)均有其对应的子进程,就算是由于父进程先行结束导致的孤儿进程,也会被init领养,使其父进程ID为1。
也因为所有的进程均有父进程,事实上,所有进程的创建,都可视为子进程创建过程。在apue一书里提及unix操作系统进程的创建,大抵上的模式都是进行fork+exec类系统调用。
理解子进程的创建执行,需要至少细分到二个步骤,包括
通过fork创建子进程环境,
通过exec加载并执行进程代码。
其间诸如继承的环境变量等细节,可以查看apue第八章相关章节。
而shell子进程(以下均称subshell),顾名思义,就是由“当前shell进程”创建的一个子进程
2:shell什么情况下会产生子进程
以下几个创建子进程的情况。(以下英文摘自info bash)
1:&,提交后台作业
If a command is terminated by the control operator `&', the shell executes the command asynchronously in a subshell.
2:管道
Each command in a pipeline is executed in its own subshell
3:括号命令列表
()操作符
Placing a list of commands between parentheses causes a subshell
environment to be created
4:执行外部脚本、程序:
When Bash finds such a file while searching the `$PATH' for a command, it spawns a subshell to execute it. In other words, executing
filename ARGUMENTS
is equivalent to executing
bash filename ARGUMENTS
说明:大致上子进程的创建包括以上四种情况了。需要说明的是只要是符合上边四种情况之一,便会创建(fork)子进程,不因是否是函数,命令,或程序,也不会因为是内置函数(buitin)或是外部程序。
此外,上边提到子进程创建与执行的二个步骤,shell子进程的创建在步骤之一并无多大差别,一般还是父进程调用fork产生进程环境,估在第二步exec的时候,是存在差别的。
shell做为解释语言程序,提供给第二步exec加载和执行的程序体并不是脚本本身,而是由第一行#!指定的,默认为shell程序,当然也可以是awk,sed等程序,在之前写过的一篇文章里:shell脚本的set id如何生效就有提及。这里不再展开讨论。
只不过子进程的执行会根据情况而有所差别,对于内置函数,exec程序体为shell程序,并在会在子shell直接调用内置函数,
而外部函数或程序,在创建了子进程环境后,大致会有二种执行情况:
1:直接exec外部程序,
比如下边例子中直接执行的sleep,pstree命令等
2:subshellexec程序体为shell程序,在此基础上会进一步创建一个子进程以执行函数。
比如下边例子中通过函数提交后台程序中的shell命令等
例:内置函数(直接在subshell里执行,不管是否通过函数)
[root@localhost shell]# mkfifo a
[root@localhost shell]# type echo
echo is a shell builtin
[root@localhost shell]# b(){ echo a>a; }
[root@localhost shell]# b &
[1