Android编译系统介绍
- 格式:pdf
- 大小:6.97 MB
- 文档页数:72
dex2oat编译dex2oat译是Android统中,基于 Dalvik Executable (DEX)式的应用程序在 Android拟机 (ART) 上执行之前必须经过的一种编译过程。
本文将对 dex2oat译的相关知识进行介绍,比如它的工作原理、编译之后的优化效果,以及一些遇到的问题。
一、dex2oat译简介dex2oat译是 Android统中的一个很重要的编译过程。
它的职责是将基于 Dalvik Executable (DEX)式的应用程序编译成 Android 拟机 (ART)以直接运行的格式OAT式(Opaque binary blob)。
这个编译过程包括了字节码分析、优化处理、调度过程等步骤,使得程序运行效率大大提高。
二、dex2oat译的工作原理dex2oat译是基于类似 Just-In-Time(JIT)的编译模式进行的,它将基于 Dalvik Executable (DEX)式的字节码编译成 Android拟机 (ART)以直接运行的非可读格式OAT式。
整个编译过程由几个小步骤组成:1.先,dex2oat译器会把基于 DEX式的应用程序中的字节码进行分析,把代码部分分解成更小的操作。
2.后,它会对代码进行优化,通过标量替换、内联展开、重排序、代码布局和混淆等技术,提高程序运行的效率。
3.后,它会将优化之后的代码编译成 OAT式的字节码,使得应用程序可以在 Android拟机 (ART) 上直接运行。
三、dex2oat译的优化效果dex2oat译的优化效果是非常明显的,尤其是对高级语言的优化效果更加强大。
通过 dex2oat译可以把应用程序中出现的热点代码提前编译,把热点代码优先执行,使得程序运行的效率更高;它还可以优化字节码的内存布局,使得程序更加紧凑,节省内存空间;它还可以把字节码重排序,把不常用的操作放到后面,把热点代码放置在前面,使得程序的访存效率更高;它还可以对字节码进行机器码编译,使得代码运行效率更高。
Android编译系统中的Android.bpAndroid.bp,是⽤来替换Android.mk的配置⽂件。
它使⽤框架来解析,最终转换成⽂件。
与Android.mk不同的是,Android.bp是纯粹的配置⽂件,不包含分⽀、循环等流程控制,也不能做算数、逻辑运算。
与此同时,⽂件也是如此。
这就产⽣了⼀些新的问题与需求——在Android项⽬上进⾏选择编译、解析配置、转换成等——应运⽽⽣。
其实就相当于Makefile编译系统的核⼼,即build/make/core/下⾯的内容。
它负责提供Android.bp的含义定义与解析,并将之转换为⽂件。
和都是由写的项⽬。
从Android Nougat开始,prebuilts/go/⽬录下新增了所需的运⾏环境,在编译时使⽤。
Android.bp以及相关⽀持,从Android Nougat开始加⼊,从Android Oreo(8.0)开始默认开启。
如果需要在Android Nougat的版本使⽤,需要在执⾏编译时添加变量。
Android.mk转换Android.bp实例下⾯,以⼀个AOSP上的简单模块,system/core/sdcard/Android.mk,来做为案例。
1.LOCAL_PATH := $(call my-dir)2.3.include $(CLEAR_VARS)4.5.LOCAL_SRC_FILES := sdcard.cpp fuse.cpp6.LOCAL_MODULE := sdcard7.LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror8.LOCAL_SHARED_LIBRARIES := libbase libcutils libminijail libpackagelistparser9.10.LOCAL_SANITIZE := integer11.12.include $(BUILD_EXECUTABLE)这是⼀个编译⼆进制可执⾏⽂件的⼩模块,内容⾮常简单。
1.安装ubuntu编译Android 5.1需要ubuntu 64位的操作系统,在百度上搜索ubuntu,到ubuntu官网下载Ubuntu 64位桌面(desktop)版本,进行安装。
安装完成后,需要更新一下ubuntu源。
Android5.1系统源码编译的磁盘空间要求较高,ubuntu 的磁盘空间需要分配60G以上,内存需要4G以上,否则容易出现编译错误等问题。
2.安装openjdk-7-jdkAndroid 5.1 用到的jdk不再是Oracle 的jdk ,而是开源的openjdk,在ubuntu安装好后,使用如下命令安装jdk:$sudo apt-get install openjdk-7-jdk安装好后,设置环境变量:$sudo gedit /etc/profile在profile文件末尾加上:JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/PATH=$PATH:$HOME/bin:$JAVA_HOME/binexport JAVA_HOMEexport PATH3.安装编译依赖的软件使用如下命令安装依赖软件:sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev libc6-dev lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline-gplv2-dev lib32z1-dev libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils xsltproc4.配置Cache使用如下命令配置cache:$sudo apt-get install ccache$source ~/.bashrc5.编译android系统源码1,初始化编译环境$. build/envsetup.sh2,选择编译目标包ps:lunch的方式有很多中,可以使用lunch命令查看,我使用最常用的$lunch full-eng3,编译$makeps: 1.make后面可以跟参数:如你的机器是四核四线程,可以使用make -j4,这样速度更快,但编译时使用的内存更多。
Android编译命令⼀、引⾔先看下⾯⼏条指令,相信编译过Android源码的⼈都再熟悉不过的。
source setenv.shlunchmake -j12记得最初刚接触Android时,同事告诉我⽤上⾯的指令就可以编译Android源码,指令虽短但过⼏天就记不全或者忘记顺序,每次编译时还需要看看⾃⼰的云笔记,冰冷的指令总是难以让我记忆。
后来我决定认真研究下这个指令的含义。
知其然还需知其所以然,这样能更深层次的理解并记忆,才能与⾃⾝的知识体系建⽴强连接,或许还有意外收获,果然如此,接下来跟⼤家分享⼀下在研究上述⼏条指令含义的过程中,深⼊了解到的Android Build(编译)系统。
⼆、编译命令准备好编译环境后,编译Android源码的第⼀步是source build/envsetup.sh,其中source命令就是⽤于运⾏shell脚本命令,功能等价于”.”,因此该命令也等价于. build/envsetup.sh。
在⽂件envsetup.sh声明了当前会话终端可⽤的命令,这⾥需要注意的是当前会话终端,也就意味着每次新打开⼀个终端都必须再⼀次执⾏这些指令。
起初并不理解为什么新开的终端不能直接执⾏make指令,到这⾥总算明⽩了。
接下来,解释⼀下本⽂开头的引⽤的命令:source setenv.sh //初始化编译环境,包括后⾯的lunch和make指令lunch //指定此次编译的⽬标设备以及编译类型make -j12 //开始编译,默认为编译整个系统,其中-j12代表的是编译的job数量为12。
所有的编译命令都在envsetup.sh⽂件能找到相对应的function,⽐如上述的命令lunch,make,在⽂件⼀定能找到function lunch(){...}function make(){...}source envsetup.sh,需要cd到setenv.sh⽂件所在路径执⾏,路径可能在build/envsetup.sh,或者integrate/envsetup.sh,再或者不排除有些⼚商会封装⾃⼰的.sh脚本,但核⼼思路是⼀致的。
Android.mk之编译⽣成可执⾏⽂件Android.mk之编译⽣成可执⾏⽂件
⼀、简介
对于学过Linux内核的来说,想要去编译⼀个⽂件,⽣成可执⾏⽂件也好,打包成库也罢,都是使⽤Makefile 来管理编译的。
那么对于Android底层开发来讲,也是需要把咱们写的代码,编译成可执⾏⽂件或者其他可⽤的⽂件,才能使⽤起来。
再Android对这些⽂件的管理当然也需要⼀个东西来管理,其名字叫Android.mk。
⼆、Android.mk
Android系统整⼀个编译程序链接的环境很庞⼤,咱们要把Android.mk的所有东西都认识会有点⿇烦。
这⾥主要介绍如何去使⽤Android.mk去把⽂件编译成:
1、可执⾏⽂件
2、动态库
3、静态库
当然还有Jar包和APK了,这两个暂时在这⾥不讨论。
三、Android.mk编译成可执⾏⽂件的⽅法
3.1、下⾯为Android.mk
LOCAL_PATH := $(call my-dir) //定义当前模块的相对路径
include $(CLEAR_VARS) //清除当前的环境变量
LOCAL_MODULE := test //编译⽣成的⽬标名
LOCAL_SRC_FILES := test.c //编译该模块需要的源⽂件
LOCAL_MODULE_PATH += $(LOCAL_PATH) //⽣成⽂件的位置
include $(BUILD_EXECUTABLE) //编译⽣成的⽂件格式
其中“my-dir”是由编译系统提供的宏函数,⽤于返回当前Android.mk所在的路径。
下⾯来看⼀个编译多个⽂件的例⼦:。
Android编译系统(Android.mk⽂件详解)【Android-NDK(Native Development Kit) docs⽂档】NDK提供了⼀系列的⼯具,帮助开发者快速开发C(或C++)的动态库,并能⾃动将so和java应⽤⼀起打包成apk。
Android.mk⽂件是GNU Makefile的⼀⼩部分,它⽤来对Android程序进⾏编译。
因为所有的编译⽂件都在同⼀个 GNU MAKE 执⾏环境中进⾏执⾏,⽽Android.mk中所有的变量都是全局的。
因此,您应尽量少声明变量,不要认为某些变量在解析过程中不会被定义。
⼀个Android.mk⽂件可以编译多个模块,每个模块属下列类型之⼀:1)APK程序⼀般的Android程序,编译打包⽣成apk⽂件2)JAVA库java类库,编译打包⽣成jar⽂件3)C\C++应⽤程序可执⾏的C\C++应⽤程序4)C\C++静态库编译⽣成C\C++静态库,并打包成.a⽂件5)C\C++共享库编译⽣成共享库(动态链接库),并打包成.so⽂,有且只有共享库才能被安装/复制到您的应⽤软件(APK)包中。
可以在每⼀个Android.mk file 中定义⼀个或多个模块,你也可以在⼏个模块中使⽤同⼀个源代码⽂件。
编译系统为你处理许多细节问题。
例如,你不需要在你的 Android.mk 中列出头⽂件和依赖⽂件。
编译系统将会为你⾃动处理这些问题。
这也意味着,在升级 NDK 后,你应该得到新的toolchain/platform⽀持,⽽且不需要改变你的 Android.mk ⽂件。
注意,NDK的Anroid.mk语法同公开发布的Android平台开源代码的Anroid.mk语法很接近,然⽽编译系统实现他们的⽅式却是不同的,这是故意这样设计的,可以让程序开发⼈员重⽤外部库的源代码更容易。
在描述语法细节之前,咱们来看⼀个简单的"hello world"的例⼦,⽐如,下⾯的⽂件:sources/helloworld/helloworld.csources/helloworld/Android.mk'helloworld.c'是⼀个 JNI 共享库,实现返回"hello world"字符串的原⽣⽅法。
【转】Android编译系统详解(三)——编译流程详解原⽂⽹址:本⽂原创作者: 欢迎转载,请注明出处和1.概述编译Android的第三步是使⽤mka命令进⾏编译,当然我们也可以使⽤make –j4,但是推荐使⽤mka命令。
因为mka将⾃动计算-j选项的数字,让我们不⽤纠结这个数字到底是多少(这个数字其实就是所有cpu的核⼼数)。
在编译时我们可以带上我们需要编译的⽬标,假设你想⽣成recovery,那么使⽤mka recoveryimage,如果想⽣成ota包,那么需要使⽤mka otapackage,后续会介绍所有可以使⽤的⽬标。
另外注意有⼀些⽬标只是起到修饰的作⽤,也就是说需要和其它⽬标⼀起使⽤,共有4个⽤于修饰的伪⽬标:1) showcommands 显⽰编译过程中使⽤的命令2) incrementaljavac⽤于增量编译java代码3) checkbuild⽤于检验那些需要检验的模块4) all如果使⽤all修饰编译⽬标,会编译所有模块研究Android编译系统时最头疼的可能是变量,成百个变量我们⽆法记住其含义,也不知道这些变量会是什么值,为此我专门做了⼀个编译变量的参考⽹站,你可以在该⽹站查找变量,它能告诉你变量的含义,也会给出你该变量的⽰例值,另外也详细解释了编译系统⾥每个Makefile的作⽤,这样你在看编译系统的代码时不⾄于⼀头雾⽔。
编译的核⼼⽂件是和,main.mk主要作⽤是检查编译环境是否符合要求,确定产品配置,决定产品需要使⽤的模块,并定义了许多⽬标供开发者使⽤,⽐如droid,sdk等⽬标,但是⽣成这些⽬标的规则主要在Makefile⾥定义,⽽内核的编译规则放在build/core/task/kernel.mk我们将先整体介绍main.mk的执⾏流程,然后再针对在Linux上编译默认⽬标时使⽤的关键代码进⾏分析。
Makefile主要定义了各个⽬标的⽣成规则,因此不再详细介绍它的执⾏流程,若有兴趣看每个⽬标的⽣成规则,可查看2. main.mk执⾏流程2.1 检验编译环境并建⽴产品配置1) 设置Shell变量为bash,不能使⽤其它shell2) 关闭make的suffix规则,rcs/sccs规则,并设置⼀个规则: 当某个规则失败了,就删除所有⽬标3) 检验make的版本,cygwin可使⽤任意版本make,但是linux或者mac只能使⽤3.81版本或者3.82版本4) 设置PWD,TOP,TOPDIR,BUILD_SYSTEM等变量,定义了默认⽬标变量,但是暂时并未定义默认⽬标的⽣成规则5) 包含,该makefile定义了两个⽬标help和out, help⽤于显⽰帮助,out⽤于检验编译系统是否正确6) 包含,config.mk作了很多配置,包括产品配置,包含该makefile后,会建⽴输出⽬录系列的变量,还会建⽴PRODUCT系列变量,后续介绍产品配置时,对此会有更多详细介绍7) 包含,该makefile会包含所有⼯程的CleanSpec.mk,写了CleanSpec.mk的⼯程会定义每次编译前的特殊清理步骤,cleanbuild.mk会执⾏这些清除步骤8) 检验编译环境,先检测上次编译结果,如果上次检验的版本和此次检验的版本⼀致,则不再检测,然后进⾏检测并将此次编译结果写⼊2.2 包含其它makefile及编译⽬标检测1) 如果⽬标⾥含有incrementaljavac,那么编译⽬标时将⽤incremental javac进⾏增量编译2) 设置EMMA_INSTRUMENT变量的值,emma是⽤于测试代码覆盖率的库3) 包含,该makefile定义了许多辅助函数4) 包含,该makefile定义了⾼通板⼦的⼀些辅助函数及宏5) 包含,该makefile定义了优化dex代码的⼀些宏6) 检测编译⽬标⾥是否有user,userdebug,eng,如果有则告诉⽤户放置在buildspec.mk或者使⽤lunch设置,检测TARGET_BUILD_VARIANT变量,看是否有效7) 包含, PDK主要是能提⾼现有设备升级能⼒,帮助设备制造商能更快的适配新版本的android2.3 根据TARGET_BUILD_VARIANT建⽴配置1) 如果编译⽬标⾥有sdk,win_sdk或者sdk_addon,那么设置is_sdk_build为true2) 如果定义了HAVE_SELINUX,那么编译时为build prop添加属性ro.build.selinux=13) 如果TARGET_BUILD_VARIANT是user或者userdebug,那么tags_to_install += debug 如果⽤户未定义DISABLE_DEXPREOPT为true,并且是user模式,那么将设置WITH_DEXPREOPT := true,该选项将开启apk的预优化,即将apk分成odex代码⽂件和apk资源⽂件4) 判断enable_target_debugging变量,默认是true,当build_variant是user时,则它是false。
linux 安卓内核编译的方法Linux操作系统以其强大的功能和灵活的配置,吸引了越来越多的开发者。
安卓系统作为一款开源的移动设备操作系统,其内核编译对于开发者来说也是必不可少的技能。
本文将向大家介绍如何使用Linux系统进行安卓内核的编译。
一、准备工作1. 确保你的Linux系统已经安装了基本的开发工具,如gcc、make、patch等。
2. 下载安卓内核源码,可以选择从官网或者github获取。
3. 创建一个用于存放编译结果的目录,如/home/user/kernel_build。
二、配置内核1. 打开终端,导航到源码目录。
2. 使用patch工具对内核源码进行修补,确保源码与当前Linux 内核版本兼容。
3. 修改Makefile文件,指定编译选项和目标。
三、编译内核1. 运行make命令进行第一轮编译,生成中间文件。
2. 运行make menuconfig,进入配置界面,对内核选项进行进一步配置。
3. 退出menuconfig,再次运行make命令进行第二轮编译。
4. 等待编译完成,检查是否有错误信息。
四、安装驱动和模块1. 将驱动程序和模块提取出来,放在适当的目录下。
2. 运行make install命令,将驱动和模块安装到内核中。
3. 验证驱动和模块是否成功安装,可以运行一些测试程序来检查。
五、打包和测试1. 将编译后的内核映像打包,可以使用kimage工具或其他适合的打包工具。
2. 将打包后的内核映像刷入模拟器或实际设备中,进行测试。
3. 运行一些应用程序,检查内核是否能够正常工作。
4. 对测试结果进行分析和优化,根据实际需求进行进一步的调整和修改。
总结:安卓内核编译是一项需要一定技能的任务,但通过本文所述的步骤,你可以轻松完成这个过程。
在编译过程中,需要注意一些细节问题,如源码的兼容性、配置选项的选择等。
此外,为了确保编译的成功率,建议在虚拟机中进行操作,以避免对真实系统造成损坏。
android.bp 编译aidl原理一、引言Android应用程序开发中,Android Interface Definition Language(aidl)是用于定义Android中的进程间通信(IPC)的重要工具。
它主要用于实现跨进程的接口调用,为Android应用程序提供了强大的通信机制。
本文将详细介绍android.bp编译aidl的原理。
二、aidl概述aidl是Android平台上的一个重要组件,它允许不同的应用或服务之间进行跨进程通信。
aidl定义了接口和实现,并生成相应的客户端和服务器代码,以实现进程间的通信。
三、编译aidl的过程1. 编写aidl文件:开发者使用文本编辑器或集成开发环境(IDE)编写aidl文件,该文件描述了需要跨进程调用的接口和实现。
aidl文件使用特殊的XML格式编写,包含了接口名、方法名、参数等信息。
2. 编译aidl:开发者使用构建系统(如Gradle)编译aidl文件。
在编译过程中,aidl工具将解析aidl文件,生成相应的Java接口和实现类。
这些生成的代码将被添加到相应的包中,并在构建过程中被包含到最终的APK文件中。
3. AIDL文件的位置:生成的Java代码通常被放置在`gen`目录下,开发者可以通过在代码中添加`import`语句来使用这些生成的代码。
四、原理分析android.bp编译aidl的原理主要基于以下几个步骤:1. 解析aidl文件:aidl工具首先解析aidl文件,生成相应的Java接口和实现类。
这些类包含了跨进程调用的接口和实现方法。
2. 生成Java代码:生成的Java代码包含了跨进程调用的接口和实现方法,以及必要的序列化和反序列化代码。
这些代码将被添加到相应的包中,并在构建过程中被包含到最终的APK文件中。
3. 添加到构建过程中:在构建过程中,生成的Java代码将被添加到相应的包中,并在编译过程中被编译为字节码。
这些字节码将被打包到最终的APK文件中,供应用程序使用。
Android编译系统介绍张长青adamzhang@目录CONTENTS一、背景知识二、设计思想三、主要流程四、关键模块五、 APK编译过程六、 Android.mk文件七、使用示例一、背景知识本章主要介绍学习Android编译系统所需要具备的一些背景知识。
1、关于Make•make 是一个命令行工具,它解释 Makefile 中的规则。
•在 Makefile 文件中描述了整个工程中所有文件的编译顺序、编译规则和编译命令。
•Makefile有自己的书写格式、关键字、函数,而且在Makefile中可以使用系统 shell 所提供的任何命令来完成想要的工作。
1、关于Make•Makefile 文件的规则包含了文件之间的依赖关系和更新此规则目标所需要的命令,例如:目标: [依赖] [命令]•Makefile已经在绝大多数的 IDE 开发环境中都在使用,已经成为一种工程化的编译方法。
1、关于Make在默认的方式下,在当前目录提示符下输入"make"命令,系统将自动完成以下操作。
(1)make工具会在当前目录下查找名为"Makefile"或"makefile"的文件,GNU Make 工具在当前工作目录中按照GNUmakefile、makefile、Makefile的顺序搜索makefile执行文件。
(2)如果找到,它会查找文件中的第一个目标去执行。
如果目标文件不存在,或是目标所依赖的文件修改时间较晚,系统就会执行后面定义的命令来生成目标文件。
1、关于Make(3)如果目标所依赖的文件不存在,make会继续查找依赖文件的生成规则,make会一层一层地去查找文件的依赖关系,直到最终编译出第一个目标文件。
在查找的过程中,如果出现错误,比如最后被依赖的文件没有找到,make就会直接退出并报错。
1、关于MakeMakefile 文件中主要包含了5项内容: 显式规则、隐晦规则、宏定义、文件指示和注释。
1、关于Make(1)显式规则显式规则说明如何生成一个或多个目标文件。
这由makefile 的书写者明确指出,包括要生成的文件,生成目标文件需要的依赖文件,生成目标文件的命令。
例如:foo.o : foo.c defs.h # foo模块,目标和依赖之间使用分号分割cc -c -g foo.cfoo.o是目标,foo.c和defs.h是目标所依赖的源文件,命令为"cc -c -g foo.c"(此行一定要以Tab键开头)。
这个规则包括以下两个主要内容:文件的依赖关系:foo.o依赖于foo.c和defs.h文件,如果foo.c和defs.h的文件日期要比foo.o新,或是foo.o不存在,那么依赖关系发生。
cc命令说明了如何生成foo.o文件。
1、关于Make(2)隐晦规则由于make有自动推导的功能,它会根据依赖关系决定源文件是否要重新编译以及源文件之间的编译顺序,所以隐晦规则可以让程序员简单方便地书写makefile文件。
(3)宏(变量)的定义在makefile中需要定义一系列的宏(变量),宏(变量)一般都是字符串,类似于C语言中的宏。
当makefile被执行时,其中的变量都会被扩展到相应的引用位置上,这一内容在前一小节已经介绍。
1、关于Make(4)文件指示包括3个部分:一个makefile文件中引用另一个Makefile文件,就像C语言中的include一样;指根据某些情况指定makefile中的有效部分,就像C语言中的预编译#if一样;定义多行的命令。
(5)注释makefile中只有行注释,和UNIX的Shell脚本一样,其注释用"#"字符开始,类似于C/C++中的"//"。
如果要在makefile中使用"#"字符,需用反斜杠进行转义,如:"\#"。
2、关于ShellShell是一种具备特殊功能的程序, 它是介于使用者和 UNIX/Linux 操作系统之核心程序(kernel)间的一个接口。
为了对用户屏蔽内核的复杂性,也为了保护内核以免用户误操作造成损害,在内核的周围建了一个外壳(shell)。
用户向shell提出请求,shell解释并将请求传给内核。
使用较广的shell有标准的Bourne shell(sh)、KornShell(ksh)、C shell(csh)、Bourne Again Shell(bash)等。
查看当前环境所用shell:echo $SHELL2、关于Shellshell的另一个重要特性是它自身就是一个解释型的程序设计语言,shell程序设计语言支持绝大多数在高级语言中能见到的程序元素,如函数、变量、数组和程序控制结构。
shell编程语言简单易学,任何在提示符中能键入的命令都能放到一个可执行的shell程序中。
本质上,shell 脚本是将命令行命令简单的组合到一个文件里面。
Shell基本上是一个命令解释器,类似于DOS下的。
它接收用户命令,然后调用相应的应用程序去执行并返回结果。
2、关于Shell——我们为什么看不懂shell程序?Linux命令使用原则:经常使用、不会就查。
2、关于Shell——我们为什么看不懂shell程序?变量本地变量:用户自定义的变量。
环境变量:用于所有用户变量,用于用户进程前,必须用export命令导出。
位置变量:$0(脚本名),$1-$9:脚本参数。
系统变量:脚本运行时的一些相关信息。
备注:很多人看不懂脚本程序,一个很重要的原因就是看不懂变量从哪里来。
其实很多的脚本语言都采用了“预先约定”的思想,像位置变量和系统变量都是预先定义含义的,你要按照它本身代表的含义去理解,才能逐步地看懂脚本程序。
2、关于Shell——我们为什么看不懂shell程序?控制结构选择结构循环结构if语句: if then else提供条件测试case 语句:允许匹配模式、单词或值for:每次依次处理列表内的信息,直至循环耗尽。
until:不常用。
条件在循环末尾,至少执行一次。
while:条件在循环头部。
2、关于Shell——我们为什么看不懂shell程序?if语句•格式1 if [ 条件]then命令fi⏹格式2if [ 条件 ] ;then命令fi或⏹格式3if [ 条件 ] then命令1 else命令2 fi ⏹格式4if [ 条件1 ]then命令1elif[ 条件2 ]then命令2else命令3fi⏹示例#!/bin/sh#ifTest#to show the method of ifecho -e "Enter the first integer:\c"read FIRSTecho -n "Enter the second integer:"read SECONDif [ "$FIRST" -gt "$SECOND" ]thenecho "$FIRST is greater than $SECOND"elif [ "$FIRST" -gt "$SECOND" ]thenecho "$FIRST is less than $SECOND"elseecho "$FIRST is equal to $SECOND"fi2、关于Shell——我们为什么看不懂shell程序?Case语句•格式case 值 in模式1)命令1 ;;……*)命令n ;;esac 示例#!/bin/sh#caseTest#to test the method of caseUSER=`whoami`case $USER inroot)echo “You can do all the operations”;;Dave)echo "You can do some operations”;;*)echo "Sorry,you can not do anything" ;;esac备注:取值后面必须为单词in,每一个模式必须以右括号结束。
取值可以为变量或常数。
取值检测匹配的每一个模式,一旦模式匹配,其间所有命令开始执行直至;;。
执行完匹配模式相应命令后不再继续其他模式。
如果无一匹配模式,使用*号捕获该值,再接受其他输入。
2、关于Shell——我们为什么看不懂shell程序?For循环•格式for 变量名in列表do命令done 示例#!/bin/sh#forTest#to test the method of forCOUNTER=0for FILES in *doCOUNTER=`expr $COUNTER + 1` doneecho "There are $COUNTER files in `pwd` "备注:当变量值在列表里,for循环即执行一次所有命令,使用变量名访问列表中取值。
嵌套循环可以将一个for循环嵌在另一个for循环里。
2、关于Shell——我们为什么看不懂shell程序?•格式until 条件do命令 done 示例#!/bin/sh#untilTest#to test the mothod of untilIS_ROOT=`who|grep root` until [ "IS_ROOT" ]doIS_ROOT=`who|grep root` sleep 5doneecho "Watch it.root in!"备注:until 执行一系列命令,直至条件为真时停止。
until循环2、关于Shell——我们为什么看不懂shell程序?•格式while 命令do命令done 示例#!/bin/sh#whileTest#to test the method of while COUNTER=0while [ $COUNTER -lt 10 ]doecho $COUNTERCOUNTER=`expr $COUNTER + 1` donewhile read LINEdoecho $LINEdone < names.txt备注:While循环用于不断执行一系列命令,也用于从输入文件中读取数据。
虽然通常只有一个命令,但在while和do 之间可以放几个命令。
命令通常用作测试条件,只有当命令的退出状态为0时,do和done之间命令才被执行,如果退出状态不是0,则循环终止。
while循环2、关于Shell——我们为什么看不懂shell程序?•格式函数名() {命令}示例1#!/bin/sh#funTest#to test the functionDATE=`date`Hello(){echo “Hello,today is $DATE”}Hello示例2#!/bin/sh#funTest#to test the function. ./HelloHello备注:所有函数在使用前必须定义,这意味着必须将函数放在脚本开始部分,直至shell 解释器首次发现它,才可以使用。