我们知道,Bash 在执行一个外部命令时,会先 fork() 一个子进程,然后在子进程里面执行 execve() 去加载那个外部程序。fork 子进程是会耗性能的,所以 Bash 会在下面几种情况下不 fork 子进程,直接在当前进程执行 execve()。

bash -c 'command'

如果用了 bash -c 的形式启动 Bash,同时 -c 选项的参数里只包含一个命令,比如 bash -c 'sleep 666',这时 Bash 不会 fork 子进程去运行 sleep 命令,它会让 sleep 直接占用自己现有的进程:

$ bash -c 'sleep 666' &

$ pstree -ap

...

|  `-bash,3117

|      |-pstree,3119 -ap

|      `-sleep,3118 666

...

3117 是我当前敲入命令的交互 Shell,3118 就是 bash -c 启动的那个进程,然后直接被替换成了 sleep,pid 还是 3118。

我们可以看一下 Bash 无法优化的情况下,进程树是什么样的:

$ bash -c 'sleep 666;ls' &

$ pstree -ap

...

|  `-bash,3117

|      |-bash,3120 -c sleep\040666;ls

|      |   `-sleep,3121 666

|      `-pstree,3122 -ap

...

这次我们给 -c 的参数包含了两个命令,sleep 和 ls,所以 Bash 不能让 sleep 占用它的进程,因为执行完 sleep 它还得去执行 ls。

bash -c 'command1 && command2 || command3 ... && commandN'

在这种由若干个 && 和 || 把若干个简单命令组成的的复合命令中,最右侧的那个(commandN)命令执行时(如果执行到的话)会进行 no-fork 优化:

$ bash -c 'sleep 1 || sleep 2 && sleep 666' &

$ pstree -ap # 等 3 秒钟后再执行这条

...

|  `-bash,3117

|      |-pstree,3126 -ap

|      `-sleep,3123 666

...

在 bash -c 'sleep 1 || sleep 2 && sleep 666' 这条命令中,一共产生过 3 个进程,bash -c 首先产生了一个进程 3123,然后 3123 又分别 fork 出两个子进程 3124 和 3125 来分别执行 sleep 1 和 sleep 2,sleep 666 没有产生新的进程,它和 bash -c 用了同一个进程,也就是 3123。这个优化在 Bash 4.4 之前没有。

( command )

用显示的子 shell 语法运行一个单独的命令,比如 ( sleep 100 ),如果不进行优化的话,这里应该先 fork 一个子 shell,然后这个子 shell 会再 fork 一个子子 shell 去运行 sleep,一共 fork 两次,再极端点:( ( ( ( ( sleep 100 ) ) ) ) ),会产生一个 5 级的子 shell(( ( ( ( ( echo $BASH_SUBSHELL ) ) ) ) ) 的确会输出 5),一共 fork 6次,然而 Bash 并不会这样做,无论你嵌套了多少级,Bash 只会 fork 一次,只产生一个子进程,然后在这个进程里执行 sleep 命令。

Bash 的 no-fork 优化的更多相关文章

  1. fork炸弹

    众所周知,bash是一款极其强大的shell,提供了强大的交互与编程功能.这样的一款shell中自然不会缺少“函数”这个元素来帮助程序进行 模块化的高效开发与管理.于是产生了由于其特殊的特性,bash ...

  2. Bash 的若干基本问题

    Bash 的若干基本问题   这里介绍一些bash启动前.后的问题,以及一些使用bash需要注意的基本问题.     1.Bash的介绍   Bash是一种Shell程序,它是一般的Linux系统中的 ...

  3. Linux基础优化与安全归纳总结

    一名运维工程师在运维岗位上时间久了,就会发现Linux优化的重要性,同时会给运维工作带来很多的便利性.本人逐渐认识到了这一点,所以特意在工作闲暇之余,通过阅读Linux相关书籍及向同事.同行高手咨询, ...

  4. 总结linux内核的一些参数优化

    sysctl命令被用于在动态地修改内核的运行参数,可用的内核参数在目录/proc/sys中. 它包含一些TCP/IP堆栈和虚拟内存系统的高级选项, 用sysctl可以读取设置超过五百个系统变量. sy ...

  5. linux进程管理(上)

    程序和进程的区别: 1.程序是一种静态资源 程序启动产生进程 2.程序与进程无一一对应原则  进程是动态的一个过程 父进程和子进程在前面提过 前台进程:执行命令时只能等待的进程为前台进程也叫异步进程 ...

  6. Ubuntu检测磁盘是否挂载

    Ubuntu默认不自动挂载磁盘. 只是学习Bash使用,需优化如使用 # file: mountAll.sh # include color support # a list of variables ...

  7. 实现mypwd和mybash

    一.pwd 1.学习pwd命令 man pwd查看pwd功能 可以得知pwd功能是打印当前目录 2.研究pwd实现需要的系统调用(man -k; grep),写出伪代码 (1)man -k direc ...

  8. Linux 用户身份与进程权限

    在学习 Linux 系统权限相关的主题时,我们首先关注的基本都是文件的 ugo 权限.ugo 权限信息是文件的属性,它指明了用户与文件之间的关系.但是真正操作文件的却是进程,也就是说用户所拥有的文件访 ...

  9. Linux进程的原理及与信号的联系

    第1节 程序.进程.守护进程.僵尸进程的区别 程序.进程.守护进程.僵尸进程: 程序:c/php/java,代码文件,静态的,放在磁盘里的数据. 进程:正在内存中运行的程序,进程是动态的,会申请和使用 ...

随机推荐

  1. python中的常用方法

    1.os模块的常用方法: >>> import os >>> >>> myFiles = ['accounts.txt', 'details.cs ...

  2. sql left join on

    select sysuser.userid,       sysuser.groupid,       sysuser.sysid,       nvl( userjd.mc,nvl(useryy.m ...

  3. java多线程系类:JUC线程池:04之线程池原理(三)(转)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--"基础篇& ...

  4. codevs 1015 计算器的改良 2000年NOIP全国联赛普及组

     时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题目描述 Description NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委 ...

  5. Matlab中使用脚本和xml文件自动生成bus模块

    帮一个老师写的小工具 在一个大工程中需要很多bus来组织信号,而为了规范接口,需要定义很多BusObject,用Matlab语言手写这些BusObject比较费工夫 所以用xml配置文件来写,也便于更 ...

  6. request.getcontextPath() 详解

    request.getcontextPath() 详解 文章分类:Java编程 <%=request.getContextPath()%>是为了解决相对路径的问题,可返回站点的根路径. 但 ...

  7. Android开发自学笔记(Android Studio)—4.2TextView及其子类

    一.引言 TextView是我们最常用的一个控件了,它类似于C# Winform程序中的Lable,Java Swing编程中的JLable,不过相对功能更强大些,但从功能上看,它其实就是个文字编辑器 ...

  8. CSS选定第k个元素

    <!DOCTYPE html> <html> <head> <title></title> <style type="tex ...

  9. Android四大组件之—— 使用服务进行后台操作

    什么是服务 服务是一个没有可视化界面的组件,它可以在后台长期运行并进行各种操作. 服务的创建 我们只需要继承Service类并实现相应的方法即可创建服务 要想启动服务,还得在AndroidManife ...

  10. 【Alpha】十天屠龙记

    团队名字: 一不小心就火了 屠龙天团少年们: 031402504 陈逸超 (组长) 031402505 陈少铭 031402511 黄家俊 031402515 翁祖航 031402516 黄瑞钰 03 ...