shell介绍:操作系统终端的命令行

shell可以理解为,软件系统提供给用户操作的命令行界面。人机交互的一种方式

我们可以使用shell对操作系统和uboot等软件系统进行交互。

shell脚本的运行机制:解释运行的

shell用源代码编写好后,源代码可以直接运行,不像C要进行编译链接。

shell脚本中的程序是解释运行的,意思就是我们的源码编写好后,在运行时,我们的shell解析器就会一行一行的对shell源码进行解释,并且逐行的运行,就是逐行解释运行。

也就是说shell脚本语言不像是我们的C语言,写完源代码后,要进行编译链接成二进制的可执行程序,完了在运行

脚本语言是在我们编写好源码后,去运行这个脚本的时候,也就是运行这个源码的时候,逐行的将我们的脚本源码转成二进制程序去给我们的CPU运行。


自己写一个shell

1、我们的shell是在linux下进行直接运行的,不像是C语言,可以在Windows下进行编写,完了之后经过Linux的gcc编译器经过处理,会直接变成了二进制程序去运行,我们的shell是直接在linux下直接运行的,编写好后,直接运行,所以如果我们在Windows中的文本去编写shell的话,是不可以直接在linux下运行的,因为在Linux中,换行符'\

n',而在Windows中换行符是'\r\n'。所以这个shell的编写我们不能在Windows下的编辑器去写,要在linux下的编辑器去写。

2、shell程序运行的方法:

比较常用的,第一种:./xx.sh 和我们运行可执行程序很像,但是这种方法去运行,要求这个shell程序必须有可执行权限去运行。

第二种:source xx.sh  source是linux下的一个命令,执行脚本程序的命令,这样去做就不需要我们shell脚本需要有可执行的权限

第三种:bash xx.sh bash是一个shell的解释器,就相当于bash是linux下的一个可执行程序,这个可执行程序直接解释运行了.sh那个文件

3、写一个hello word 

第一行的#!/bin/sh 意思就是说,我们这个脚本文件,将来是从#!开始后面的,用/bin下的sh程序执行的。

echo是linux下的一个命令就是打印的意思。

4、shell脚本其实就是一个把我们命令行下输入(键入的命令),写到了shell中变成了shell中的程序,执行shell去做。所以shell就是为了方便我们,我们可以不用在命令行下手工去输入,多次要重复做的事情,可以直接通过shell简化我们的操作。

shell是弱类型语言,就是变量的定义没有明确的类型,在shell中,变量没有类型。

所以shell中,

变量的定义是没有类型的,可以初始化,比如定义一个变量string并初始化,string="hello word"就是定义了一个string变量,并且初始化为hello word。在shell中等号赋值的两边是不能有空格的。

变量的赋值就是跟C一样赋值。

变量的引用,要用$符号去引用。$符号就变量解引用符号。

注意:在使用$符号时,$符号后面的字符串会被解析成一个变量,并对这个变量去解析,如果后面的字符串是没有定义赋值的,那么去解析这个没有定义并赋值的变量,就会被解析成,赋值为空的变量,引用时会打印空。

shell中,使用字符串可以不加双引号,但是如果不加双引号的缺陷就是,不能输出"或者转义字符。

加单引号就是直接字面全部输出,不会替换。

加双引号,如果双引号中有转移字符(\" \$ )等,则输出的内容中,会将转义字符进行转义,变成" $符号

反引号,引起来的部分表示linux中的命令,我们给变量赋值时,有的时候想给变量赋的值是执行linux命令的返回值

如:PWD=`pwd` , 双引号中可以包含反引号MYPATH="`pwd`\include" 将当前的绝对路径的赋值给MYPATH

shell中的if判断结构

典型基本的我们能用到的if语句格式

if [表达式]; then

xxx

else

xxx

fi

这个的格式就是这样,其实和C的差不多,; then 是格式固定的 fi 是if的结束语


1、判断一个文件a.txt是否存在,-f

if [ -f a.txt ] -f 就是判断一个文件是否存在,存在则成立。  

2、判断一个目录是否存在, -d

3、判断字符串是否相等"str1" = "str2"

4、判断数字是否相等(-eq)、大于(-gt)、小于(-lt)、大于等于(-ge)、小于等于(-le)

5、判断字符串是否为空(-z

6、if语句中使用-o表示逻辑或

7、逻辑&&和逻辑或||在shell中,可以简写if判断式

[ -z $str ] || echo "yes"  意思就是if判断的简写,如果str为空,则成立,就不会执行逻辑或||后面的语句,如果str不为空,则不成立,则执行逻辑或||后面的语句。就跟C语言中的逻辑或||一样,如果if表达式中的||逻辑符号前面的成立了,则不用执行||后面的了,如果||前面的不成立则执行||后面的

[ -f a.txt ] && touch b.txt  如果a.txt文件存在,则创建不b.txt


shell中的循环结构:

for循环格式

for i in 1 2 3 4 5 xxx   (in 后面的东西可以是数字,字符)

do

echo $i

done

while循环格式 打印1到10

i=1

j=11

while [ $i -lt $j ]; do

echo $i

i=$(($i+1))

done

echo创建一个文件,并且追加输入文件

>xx.txt创建一个文件xx.txt

>>xxx.txt在这个文件xxx.txt中,追加内容

echo "text" > a.txt 创建一个文件a.txt,并且将text输入到a.txt

echo "zhuijia" >> a.txt 在a.txt文件中追加zhuijia内容进去。




调用shell程序的传参

$#表示调用shell程序时,给shell传参的个数

$0、$1、$2、$3......依次表示传参的各个参数


在C语言中,我们argc是传参的个数,这个传参的个数包括./a.out

在shell中,我们$#表示给shell传递的参数个数,但是这个个数不包括 source loop.sh 

在C语言中,我们的argv[0]中的参数表示./a.out argv[1]参数表示./a.out 后面的那个参数,以此类推

在shell中,我们$0表示执行我们这个shell的解析可执行程序的名字

$1表示我们第一个有效参数,之后以此类推

shell中的$# $1等内置的变量,不仅可以被我们来传不同的参进去进行改变,也可以通过shift这个指令来改变,shift一次就可以让我们参数$1 $2 $3等,左移掉一个,使得$#的值少一,原先$1的值被移走了,现在的$2值变成了原先的$1值了。




二、Makefile 

目标、依赖、命令

目标就是我们最终要生成的东西。

依赖是用来生成 目标的原材料

命令就是加工方法

所以make的过程就是将我们依赖加工成目标的过程

通配符%和makefile自动推导(规则)

%在makefile中是通配符,意思就是代表一个或者多个字符,%.o 意思就是代表所有的.o文件

我们make xxx(我们的目标时)或者make,makefile的规则就开始了,首先会去看这个目标的依赖,存在不存在,如果不存在就会把这个依赖作为目标去找这个依赖的依赖,如果找到了这个依赖的依赖就会去执行的这个依赖的依赖的命令,将我们的这个依赖的依赖加工成依赖的目标,这时最开始的目标就能找到这个依赖了,就可以进行用命令将这个依赖加工成目标了。

比如 led.bin:led.o 

命令

%.o: %.S

命令

上面的led.bin就是我们make的目标,led.o就是最开始目标的依赖,结果在当前的目录下找不到这个依赖,就又会把这个依赖作为目标,%.o把变成了这个依赖的目标,这个目标又去看他的依赖存在不存在,发现在当前的目录下找了.S结尾的文件,就会执行这个依赖的命令,将这个依赖用命令加工成.o文件,这样我们的led.bin这个目标就找到了他的依赖了,就可以执行命令,将led.o这个依赖加工成led.bin这个目标

makefile中定义变量和使用变量

makefile中定义变量、使用变量,和我们的shell脚本中是类型的,因为变量都是没有类型的,变量的引用时也是用$去引用。

伪目标(.PHONY)

伪目标的意思就是,我不生成这个目标,这个目标不是一个文件或者其他东西,但是我们想要执行这个目标下的命令,伪目标是没有依赖的,因为我只想执行这个伪目标的命令,makefile中,clean就是一个伪目标。

为了声明这个目标是一个伪目标,让别人一眼就知道,所以通常会用.PHONY去声明这些伪目标,如:

.PHONY clean (声明clean是一个伪目标)

clean

rm *.o *.elf *.bin 


makefile中引用makefile(include 指令)

因为当工程很大的时候,可能需要写好几个makefile,所以我们需要在主的makefile中去引用其他的makefile,引用方法就是用include的指令,这个指令就是原地展开的意思,跟我们C语言中的#include预处理阶段的工作任务一样,将包含的东西原地展开

makefile的补充学习:

1、makefile中注释用#

2、命令前面的@用来静默执行

makefile的命令行中前面的@表示静默执行

什么意思呢,makefile在默认的情况下,makefile执行命令的时候,是先把这行命令给打印出来,完了之后在去执行这行命令。如果你不想看到这行命令,直接去执行这行命令,就可以在这行命令前面加@,静默执行就可以了

3、makefile中的几种变量赋值运算符

(1)?= 意思就是如果前面的变量没有被赋过值了,就执行这条赋值

(2)+= 意思是用来给一个已经被赋值的变量,用来接续赋值

(3)= 最简单的赋值

(4):= 一般情况下也是赋值

以上这两个,在大部分的情况下,都是一样的。但是有些情况下是不一样的。

= 在赋值一个变量的时候,我在$解析这个变量的时候,解析出来的这个变量的值是最后一次用=号赋值给这个变量的值,不是说是解析这个变量的值,一定是上面出现的=赋值给的值,要向后面看看有没有用=号再次给这个变量赋值,如果后面有的话,哪怕解析这个变量是前面,解析的值也会是后面的值

:= 来赋值变量的时候并解析的时候,就是这个变量前面所赋值的值,与后面在给这个变量赋值无关了。

当我们解析一个变量的时候,我们就看这个变量的被赋值的时候用的是:= 还是= 如果用的是:=则就往前面看这个变量最后一次被赋值的值,如果是= 就要往后看这一个变量最后一次被赋值的值

makefile中的环境变量

makefile中环境变量就是用export导出的普通变量,一般环境变量在makefile中都是大写的,普通变量是用小写的。

环境变量和普通变量的区别在makefile中,在makefile中,环境变量是被export导出的叫做环境变量,它是可以被整个工程中的makefile共享的变量,而普通变量只是在当前的makefile中可以被使用。

makefile中还有一些环境变量是我们在执行环境下给传进去的环境变量,我们可以在make的时候带上参数

make CC=arm-linux-gcc 这样可以让makefile里面CC这个变量的值变成我们这次make时给的参数的值。

makefile的补充学习2:

makefile中使用通配符

* 任意个字符

? 一个字符

[] 将其中的内容依次的去和我们外面的进行匹配。

% 也是代表任意个字符,不同的是,%只用在规则描述中,,所以又叫规则通配符

%.o : %.S 这就是规则描述

arm-linux-gcc -o $@ $< -c -nostdlib

makefile中的自动变量

常用的自动变量

$@ 表示规则的目标文件名 

$> 规则的依赖文件名

$^ 依赖的文件集合