这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» 软件与操作系统» 通过一个脚本搞懂fork、source和exec

共5条 1/1 1 跳转至

通过一个脚本搞懂fork、source和exec

高工
2023-02-17 17:45:15 打赏
前言

这是一个经常在面试时被问到的一个问题,对于刚刚接触shell的初学者来说,确实不太好搞明白这三者的区别,下面我通过两个脚本来帮助你理解它们。

前置知识点

1)我们所执行的任何程序,都是由父进程(parent process)所产生出来的一个子进程(child process),子进程在结束后,将返回到父进程去。此现像在Linux系统中被称为fork。当子进程被产生的时候,将会从父进程那里获得一定的资源分配、以及继承父进程的环境( 如环境变量)。

2)环境变量大体可以分为三类:

  • 内置变量:系统提供,不用定义,不能修改,比如$#,$?,$*,$0等
  • 环境变量:系统提供,不用定义,可以修改,当前进程及其子进程中使用,比如PATH,PWD,SHELL等
  • 用户变量(本地变量):用户定义,可以修改,在当前进程使用,比如var=123等


3)环境变量只能从父进程到子进程单向继承。换句话说:在子进程中的环境如何变更,均不会影响父进程的环境。

4)先准备两个示例脚本:

vi 1.sh ##内容如下


#!/bin/bashA=aminglinuxecho "PID for 1.sh before exec/source/fork:$$"export Aecho "1.sh: \$A is $A" case $1 in fork) echo "using fork" bash 2.sh ;; source) echo "using source" source 2.sh ;; exec) echo "using exec" exec ./2.sh ;; *) echo "using fork" bash 2.sh ;;esac echo "PID for 1.sh after exec/source/fork:$$"echo "1.sh: \$A is $A"

vi 2.sh ##内容如下


#!/bin/bashecho "PID for 2.sh: $$"echo "2.sh get \$A=$A from 1.sh"A=opsexport Aecho "2.sh: \$A is $A"

给两个脚本执行权限


chmod +x 1.sh 2.sh

Fork

Fork,字面上就是派生的意思,在当前shell中(可以是脚本,也可以是命令行终端)去执行一个bash命令,那么就会派生一个sub-shell,也就是所谓的子shell。这个过程就是fork。

image.png

Fork模式下,子shell会继承父shell的环境变量、用户变量,当子shell结束时,子shell里面产生的环境变量并不会带到父shell中。
通过执行示例脚本,来验证上面的结论:

bash 1.sh fork

image.png

1)1.sh的PID为15242也就是父shell的PID,而2.sh的PID为15243,这个是子shell的PID。2)在1.sh里定义了变量A,值为aminglinux,然后fork了一个子shell去执行了2.sh,在2.sh里变量A的值是ops,但是当2.sh执行完后,再回到1.sh,变量A的值依然是aminglinux。

Source

Source模式下,子shell执行时获取的环境变量会会影响到父shell。与fork的区别在于,不会额外打开一个sub-shell来执行被调用的脚本,而是在同一个shell中执行。所以,被调用的脚本中声明的变量和环境变量, 都可以在主脚本中得到和使用。

下面来执行下示例脚本:


bash 1.sh source

图片

1)无论1.sh还是2.sh,PID都是17164,这说明source并不会开启sub-shell,而是和父shell使用了同一个进程。

2)source 2.sh后,变量A的值变成了ops,而后也被带到了1.sh里。

Exec

Exec模式下,一旦执行了子shell,就不会再去执行父shell了。它与fork不同,不需要新开一个sub-shell来执行被调用的脚本,被调用的脚本与父shell在同一个shell内执行,这个特性和source一样。但是使用exec调用一个新脚本后, 父shell中exec之后的内容就不会再执行了。

我们来看示例脚本执行结果:


bash 1.sh exec

image.png

1)1.sh和2.sh的PID都是18633,这说明exec和source一样,并不会开启sub-shell,而是和父shell使用了同一个进程。

2)exec调用完2.sh之后,脚本就结束了,没有再继续,这是exec的特性!

总结
  • source命令: 不创建子进程,在当前Shell进程中执行脚本,会将新的环境变量传递到当前shell来。
  • exec命令: 不创建子进程, 在当前Shell进程中执行脚本,父脚本中exec行之后的内容不会执行。
  • fork属于系统调用, 会创建一个子进程, 父进程会阻塞等待子进程执行结束, 然后继续往下执行,子进程里的环境变量不影响父进程。






关键词: 脚本 source fork exec

工程师
2023-02-17 19:51:27 打赏
2楼

感谢楼主的分享


工程师
2023-02-17 19:52:17 打赏
3楼

感谢楼主的分享


工程师
2023-02-17 19:56:08 打赏
4楼

谢谢分享


工程师
2023-02-17 20:11:36 打赏
5楼

谢谢分享


共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]