2018-11-27 16:17:56 u014471752 阅读数 270
  • Linux系统编程第06期:从零实现一个shell解释器

    在Linux环境下,shell是一个位于操作系统和用户应用程序之间的工具,我们在shell终端下敲入命令并运行,或者直接运行 一个脚本文件,这背后都是shell在帮助我们解析命令并创建一个个子进程去执行。为了更深一层去探寻shell背后的机制原理、加深对Linux系统的理解, 本课程将带领大家,从零开始一步一步实现一个shell解释器:wsh,主要实现以下功能: * 可以在shell交互窗口中执行用于输入的shell命令 * 实现shell的内建命令:cd、exit、export等 * 支持管道命令 | * 支持进程的后台执行 * 支持脚本的解析和运行 * 支持脚本简单的if-else控制语法 * 支持信号的处理操作

    353 人正在学习 去看看 王利涛

Linux环境变量之export详解

 

linux中经常会配置环境变量的值,其中在配置有些环境变量的值之前会加export, 有些则不会,尤其在.bashrc .profile /etc/bash.bashrc中配置用户或者系统的环境变量时会产生一定的疑问。

 

归根结底,使用export与否,取决于希望该变量的作用域,使用export的话,则其作用域在当前shell启动的所有程序中,不使用则仅仅作用于当前shell,并不能作用于子进程中。

 

example_1:

非.bashrc .profile /etc/bash.bashrc中设置环境变量时:

user@pc:~$ VAL_TS='hello'                                        #定义非export变量 VAL_TS
user@pc:~$ echo $VAL_TS                                          #输出变量 VAL_TS 的值
#结果
hello

user@pc:~$ echo 'echo "val is :" $VAL_TS' > test.sh              #添加脚本语句到 test.sh
user@pc:~$ ./test.sh                                             #执行脚本 test.sh
#结果
val is :                                                         #解析不到VAL_TS变量的值

user@pc:~$ export EX_VAL_TS='world'                              #定义export变量 EX_VAL_TS
user@pc:~$ echo $EX_VAL_TS                                       #输出变量 EX_VAL_TS
#结果
world

user@pc:~$ echo 'echo "export val is :" $EX_VAL_TS' >> test.sh   #添加脚本语句到 test.sh
user@pc:~$ ./test.sh                                             #执行脚本 test.sh
#结果
val is :
export val is : world                                            #可以解析到变量EX_VAL_TS的值

 

example_2:

当在~/.bashrc中添加当前用户的环境变量时,非export变量的作用域仅为当前用户的所有交互式shell, 而不会作用域非交互式shell。

user@pc:~$ echo 'VAL_TS="hello, no export"' >> ~/.bashrc            #添加非export变量赋值到.bashrc
user@pc:~$ source ~/.bashrc                                         #使.bashrc生效
user@pc:~$ echo $VAL_TS                                             #输出变量 VAL_TS 值
#结果
hello, no export

user@pc:~$ echo 'echo "val is :" $VAL_TS' > test.sh                 #添加脚本语句到脚本 test.sh
user@pc:~$ ./test.sh                                                #执行脚本 test.sh
#结果
val is :                                                            #脚本中并没有变量值

user@pc:~$ echo 'export EX_VAL_TS="hello, export"' >> ~/.bashrc     #添加export变量赋值
user@pc:~$ source ~/.bashrc                                         #使.bashrc生效
user@pc:~$ echo $EX_VAL_TS                                          #输出变量 EX_VAL_TS 值
#结果
hello, export

user@pc:~$ echo 'echo "export val is :$EX_VAL_TS' >> test.sh        #添加脚本语句到脚本
user@pc:~$ ./test.sh                                                #执行脚本 test.sh
#结果
export val is :hello, export                                        #脚本中获取到了变量值

总结:

export决定了环境变量的作用范围,显式的export作用的都是交互式shell,而在非交互式shell中如果需要用到某个环境变量,则需要在其赋值时加前缀 export

 

2017-12-19 19:15:26 yang_quan_yang 阅读数 11053
  • Linux系统编程第06期:从零实现一个shell解释器

    在Linux环境下,shell是一个位于操作系统和用户应用程序之间的工具,我们在shell终端下敲入命令并运行,或者直接运行 一个脚本文件,这背后都是shell在帮助我们解析命令并创建一个个子进程去执行。为了更深一层去探寻shell背后的机制原理、加深对Linux系统的理解, 本课程将带领大家,从零开始一步一步实现一个shell解释器:wsh,主要实现以下功能: * 可以在shell交互窗口中执行用于输入的shell命令 * 实现shell的内建命令:cd、exit、export等 * 支持管道命令 | * 支持进程的后台执行 * 支持脚本的解析和运行 * 支持脚本简单的if-else控制语法 * 支持信号的处理操作

    353 人正在学习 去看看 王利涛

最近研究Gstream的一些东西分享给大家,通过rtsp进行取流,playbin自行构建链路

##环境配置

  • Ubuntu16 之后自带Gstreamer 的库,可以直接用无需安装

  • 代码编译运行前需要设置如下环境变量:

 export LD_LIBRARY_PATH=/usr/local/lib
 export GST_PLUGIN_PATH=/usr/local/lib:/usr/lib/x86_64-linux-gnu/gstreamer-1.0

##命令行格式
一个用于test的rtsp地址:
rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov

gst-launch-1.0 playbin uri=rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov

##代码形式

#include <gst/gst.h>  

int main(int argc, char *argv[])
{  
    GstElement *pipeline;  
    GstBus *bus;  
    GstMessage *msg;  
    
    /* Initialize GStreamer */  
    gst_init (&argc, &argv);  
    
    /* Build the pipeline */  
    pipeline = gst_parse_launch ("playbin uri=rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov", NULL);  
    
    /* Start playing */  
    gst_element_set_state (pipeline, GST_STATE_PLAYING);  
    
    /* Wait until error or EOS */  
    bus = gst_element_get_bus (pipeline);  
    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);  
    
    /* Free resources */  
    if (msg != NULL)  
    gst_message_unref (msg);  
    gst_object_unref (bus);  
    gst_element_set_state (pipeline, GST_STATE_NULL);  
    gst_object_unref (pipeline);  
    return 0;  
}  

编译使用注意:

 export LD_LIBRARY_PATH=/usr/local/lib
 export GST_PLUGIN_PATH=/usr/local/lib:/usr/lib/x86_64-linux-gnu/gstreamer-1.0
 gcc main.c -o main -Wall $(pkg-config --cflags --libs gstreamer-1.0)

如果想了解,Gstreamer播放本地视频开有参考我另一篇文章:
Qt使用GStreamer播放视频(linux环境下)

2020-03-16 21:33:40 qq_39827677 阅读数 62
  • Linux系统编程第06期:从零实现一个shell解释器

    在Linux环境下,shell是一个位于操作系统和用户应用程序之间的工具,我们在shell终端下敲入命令并运行,或者直接运行 一个脚本文件,这背后都是shell在帮助我们解析命令并创建一个个子进程去执行。为了更深一层去探寻shell背后的机制原理、加深对Linux系统的理解, 本课程将带领大家,从零开始一步一步实现一个shell解释器:wsh,主要实现以下功能: * 可以在shell交互窗口中执行用于输入的shell命令 * 实现shell的内建命令:cd、exit、export等 * 支持管道命令 | * 支持进程的后台执行 * 支持脚本的解析和运行 * 支持脚本简单的if-else控制语法 * 支持信号的处理操作

    353 人正在学习 去看看 王利涛

LInux Shell程序设计

将指定路径加到环境变量$PATH

PATH=$PATH:绝对路径
export PATH

一、变量

1.用户定义的变量

  • 给变量赋值时,等号左右不能有空格
  • $:访问变量
a=33
echo $a

只读变量

readonly a

公共变量

export a

显示变量

echo $a

清除变量

  • set : 显示所有本地定义的变量
unset a

2.shell定义的变量

  • 所有环境变量均为大写

设置环境变量

TEMPVAR=123
export TEMPVAR

显示环境变量

  • 查看所有环境变量
env

清除环境变量

unset TEMPVAR 

常用的shell环境变量

环境变量 含义
HOME 保存注册用户主目录的绝对路径名
PATH 保存路径(冒号分隔)
TERM 终端类型
UID 当前用户标识符
PWD 当前工作目录的绝对路径
PS1 主提示符 特权用户:# 普通用户:$
PS2 辅助提示符:>
IFS 缺省域分隔符 空格、tab
LOGNAME 保存登录名
SHELL 保存缺省shell /etc/passwd中设置

3.位置参数

$1:shell取第一个参数 从1开始
$0:表示当前执行shell程序名(不是位置参数)

4.预定义变量

  • 不能重定义
预定义变量 含义
$0 当前执行的进程名
$# 位置参数的数量
$* 所有位置参数的内容
$? 命令执行后返回的状态 0:成功 1:失败
$$ 当前进程的进程号
$! 后台运行的最后一个进程号

5.参数置换的变量

  • 中间没有空格
  • shell中不能为位置参数赋值
a=${b-200}
如果参数b有值则a=b,否则a=200
a=${b=200}
如果参数b有值则a=b,否则a=200,b=200
a=${b?info}
如果参数b有值则a=b,否则显示 info并退出,如果Info缺省则显示标准信息
a=${b+200}
如果参数b有值,则a=200,否则不置换

二、shell中的引用

1.双引号 “”

  • 不能消除 $ ,\ ,"",反引号`四种

2.单引号 ‘’

  • 消除单引号里面所有特殊字符的含义

3.反引号 `

  • 反引号里的内容作为系统命令
  • 输出变量为命令执行的结果

4.反斜杠 \

  • 屏蔽特殊含义

三、Shell脚本

  • 第一行:#!/bin/bash ——使用bshell解释器
  • 第二行:脚本名称
  • 注释:#

1.eval

  • eval args :将args组合成一个命令执行

2.exec

  • 执行完退出进程

3.export

  • 变量可以带到子shell

4.readonly

  • 将shell变量标识为不可变

5.read

  • 从标准输入设备读入一行,分解成若干字,赋值给shell程序内部定义的变量。

6.shift

  • 在程序中每使用一次shift语句,都使所有的位置参数依次向左移动一个位置,并使位置参数“$#”减1,直到减到0。

7.wait

  • shell等待在后台启动的所有子进程结束。wait的返回值总是真。

8.exit

  • 退出shell程序

9.source(等价于.)

  • 在当前shell环境下读入指定的shell程序文件并依次执行文件中的所有语句。
  • source 文件名(可以不拥有可执行权限)

10.":"空命令

  • 通常放在行的最左边,实际不作任何命令,只返回出口代码0

四、程序流程控制

1.测试命令

1. test "abc" = "def" #注意等号左右空格
2. [ "abc" = "def" ] #注意等号,括号左右空格
[ -z $HOME ] #真为0

=,!=,>,<
-z(字符串是否为空) 1:非空
-n(字符串是否非空)

文件测试

-e 文件名 :如果文件存在则为真
-r 文件名 :如果文件存在且可读则为真
-w 文件名 :如果文件存在且可写则为真
-x 文件名 :如果文件存在且可执行则为真
-s 文件名 :如果文件存在且非空则为真
-d 文件名 :如果文件存在且为目录则为真
-f 文件名 :如果文件存在且为普通文件则为真
-c 文件名 :如果文件存在且为字符型特殊文件则为真
-b 文件名 :如果文件存在且为块特殊文件则为真

逻辑操作符:

-a :逻辑与,操作符两边均为真,结果为真,否则为假。
-o :逻辑或,操作符两边一边为真,结果为真,否则为假。
! :逻辑否,条件为假,结果为真。

混合命令条件执行

使用&&:command1 && command2,这种命令执行方式相当地直接。&&左边的命令(command1)返回真(即返回0,成功被执行)后,&&右边的命令(command2)才能够被执行;

使用||:command1 || command2,||的作用有一些不同。如果||左边的命令(command1)未执行成功,那么就执行||右边的命令(command2);或者换句话说,“如果这个命令执行失败了|| 那么就执行这个命令”>

command1 && command2 && command3,当command1, command2成功时才执行command3 >

command1 && command2 || comamnd3,仅当command1成功,command2失败时才执行command3

2.流控制

两个(())表示执行c语言代码

2.1 if
if 条件1
             then 命令1
             elif 条件2
             then 命令2
             else 命令3
fi
  • if语句必须以单词fi
  • 必须将then部分放在新行
#!/bin/bash
var=$1
if [ $var \< "9" ]
then
   echo "less than 9"
else
   echo "more than 9"
fi

在这里插入图片描述

2.2 case
case "字符串变量" in

  值1)指令1...

;;

  值2)指令2...

;;

      ......

      *)指令3...
      ;;

esac
#!/bin/bash
var=$1
case $var in
	1)
		echo "1"
		;;
	2)
		echo "2"
		;;
	*)
		echo "others"
		;;
esac

在这里插入图片描述

2.3 for
for 变量 in 列表; 
do 
    循环体
done 
#!/bin/bash
# sum of 1 to 100
Sum=0
for i in {1..100};
do
let Sum=$Sum+$i
done
echo "Sum is $Sum"
2.4 while
while 条件(或命令);
do 
    循环体
done 
#!/bin/bash
# sum of 1 to 100
Sum=0
i=0
while ((i<10));
do
let Sum=$Sum+$i
let i=$i+1
done
echo "Sum is $Sum"
2.5 until 直到条件为真才停止循环
until [ 测试条件 ];
do
语句 #可以是多条语句
done
#!/bin/bash
# sum of 1 to 100
var=10
until [ $var -lt 1 ];
do
echo $var
var=$(($var-1))
done

练习1:cut
cut -d : -f 1 /etc/passwd | grep "user$i" 2>> /tmp/etc.err || sudo useradd user$i
##
cut:裁剪 -d:指定间隔符进行裁剪
1:裁剪的第一块
cut -d : -f 1 /etc/passwd:裁剪出第一列
2:表示出错
|:管道
||:逻辑或
grep "user$l":查找user i
##
#用:裁剪 /etc/passwd 内容取第一列 查找 useri 如果错误, 结果重定向到 /tmp/etc.err 如果执行不成功 增加用户 user1 
练习2:乘法表
#!/bin/bash
for((i=0;i<=9;i++))
do
for((j=1;j<=i;j++))
do
let k=i*j
echo -n "$i*$j=$k"
done
#换行
echo " "
done
  • echo -n: 不换行
    在这里插入图片描述
算数运算
  • let expr 只能计算整数

let

  • 不用空格分开
  • 变量计算不用$

expr

  • 运算符两边要有空格
  • *乘法要转义\*
  • 外层要有反引号``

六、Shell命令分组

“()” 和 “{}”

一定注意{}里面的内容要有空格和分号

  • 用(command_list;)将一组命令括起来,则这些命令会由子shell来完成,能保证所有的改变只对子进程产生影响,而父进程不受任何干扰.
#!/bin/bash
echo "test ()"
NUMBER=1
(A=2;B=2;NUMBER=`expr $A + $B`;echo $NUMBER) 
echo $NUMBER
  • {command_list;}则在当前shell中执行。"{}"用于将顺序执行的命令的输出结果用于另一个命令的输入。
#!/bin/bash
echo "test {}"
NUMBER=1
{ A=2;B=2;NUMBER=`expr $A + $B`;echo $NUMBER; }
echo $NUMBER

在这里插入图片描述

七、Shell信号

  • kill –l 命令看到系统中全部可用的信号名

在这里插入图片描述
shell编程只需关心 1 2 3 15

  • 1 SIGHUP 挂起或父进程被杀死
  • 2 SIGINT 来自键盘的中断信号,通常是<CTRL-C>
  • 3 SIGQUIT 从键盘退出
  • 9 SIGKILL 无条件终止
  • 11 SIGSEGV 段(内存)冲突
  • 15 SIGTERM 软件终止(缺省杀进程信号)

1.trap 捕获信号

  • trap ‘commands’ signal-list
#!/bin/bash
#trap
trap "my_exit" 2
LOOP=0
my_exit()
{
echo "You just hit <CTRL-C>,at number $LOOP"
echo "I will now exit"
exit 1
}
while :
do 
LOOP=`expr $LOOP + 1`
echo $LOOP
done

信号2 SIGINT 来自键盘的中断信号
在这里插入图片描述

八、bash程序的调试

bash -x 程序名
  • -n:测试shell脚本语法结构,只读取shell脚本但不执行
  • -x:进入跟踪方式,执行命令时把命令和它们的参数显示出来
  • -e:非交互方式,如果一个命令失败就立即退出
  • -I:交互方式
  • -k:从环境变量中读取命令的参数
  • -r:限制方式,不能执行:cd, 更改PATH,指定全路径名,输出重定向操作
  • -t 执行命令后退出(shell exits)
  • -u 置换时把未设置的变量看作出错
  • -v verbose,当读入shell输入行时把它们显示出来

1.-x -v

  • 通常使用-x进行跟踪执行,执行并显示每一条指令。
  • "-v"选择项使shell在执行程序的过程中,把它读入的每一个命令行都显示出来,
  • "-x"选择项使shell在执行程序的过程中把它执行的每一个命令在行首用一个“+”加上命令名显示出来。并把每一个变量和该变量所取的值也显示出来。
  • 主要区别在于: “-v"打印出命令行的原始内容,而”-x"则打印出经过替换后的命令行的内容

九、Linux函数库

  • 静态函数库:在程序执行前就加入到目标程序中。是一个普通的目标文件的集合,.a为后缀
  • 共享函数库:当一个可执行程序在启动的时候被加载的函数。命名必须以“lib”作为前缀,然后是函数库的名字,然后是“.so”,最后是版本号信息。

1. gcc

  • gcc 是 GNU 的 C 和 C++ 编译器

2.Linux系统中可执行文件的两种格式

  • a.out格式
  • ELF格式:很容易实现共享库。ELF格式已经被Linux系统作为标准的格式采用
    gcc编译程序产生的所有的二进制文件都是ELF格式的文件(即使可执行文件的默认名仍然是a.out)

3. GNU C 的使用

3.1 基本语法
gcc [options] [filenames]
3.2 选项

当不用任何选项编译一个程序时,GCC将会建立(假定编译成功)一个名为a.out的可执行文件。

  • gcc选项

-o: 用 -o 编译选项来为将产生的可执行文件指定一个文件名来代替 a.out。
例:gcc –o count count.c

-c: 告诉GCC仅把源代码编译为目标代码而跳过汇编和连接的步骤。这个选项使用的非常频繁,因为它使得编译多个C程序时速度更快并且更易于管理。缺省时GCC建立的目标代码文件有一个.o的扩展名。
例:gcc –c test2.c

-E : 只运行 C 预编译器。
-S : 编译选项告诉 gcc 在为 C 代码产生了汇编语言文件后停止编译。
-shared: 生成共享目标文件。通常用在建立共享库时。
-static: 禁止使用共享连接。

  • 警告选项

在gcc中用开关-Wall控制警告信息
例: gcc –Wall -o test3_1 test3_1.c

-w 不生成任何警告信息。

  • 查找选项
    -gcc一般使用默认路径查找头文件和库文件。如果文件所用的头文件或库文件不在缺省目录下,则编译时要指定它们的查找路径。

-I选项:指定头文件的搜索目录
例:gcc –I/export/home/st –o test1 test1.c

-L选项:指定库文件的搜索目录
例:gcc –L/usr/X11/R6/lib –o test1 test1.c

  • 优化选项
    优化选项可以使GCC在耗费更多编译时间和牺牲易调试性的基础上产生更小更快的可执行文件。这些选项中最典型的是-O和-O2选项。

-O0: 不进行优化处理。
-O: 告诉GCC对源代码进行基本优化。这些优化在大多数情况下都会使程序执行的更快。
-O: 告诉GCC 产生尽可能小和尽可能快的代码。-O2选项将使编译的速度比使用-O时慢。但通常产生的代码执行速度会更快。
-O3: 比 -O2 更进一步优化,包括 inline 函数。

  • 版本选项

-v: 用户将会得到自己目前正在使用的gcc的版本及与版本相关的一些信息。
-V : 如果安装了多个版本的gcc,并且想强制执行其中的某个版本,可以用命令通知系统用户要使用的版本。
例:gcc -V7.5.0 -v

  • 宏定义选项

-D MACRO : 缺省则以字符串“1”定义 MACRO 宏。
-D MACRO=DEFN: 以字符串“DEFN”定义 MACRO 宏。
-U MACRO: 取消对 MACRO 宏的定义。

  • 调试和剖析选项
    使用调试选项后,gcc在进行编译的时候,在目标文件(.o)和创建的可执行文件中插入额外信息,这些额外信息使gdb能够判断编译过的代码和源代码之间的关系。

-g: 告诉GCC产生能被 GNU 调试器使用的调试信息以便调试你的程序。
例:gcc –g –o test3 test3.c

-pg:告诉GCC在你的程序里加入额外的代码,执行时,产生gprof用的剖析信息以显示你的程序的耗时情况。

3.3多个源文件生成一个可执行文件
  • 方法1:
gcc –Wall –o mytest  test1.c test2.c test3.c
  • 方法2:
gcc -Wall -c  test1.c
gcc -Wall –c  test2.c
gcc -Wall –c  test3.c 
gcc –o  mytest  test1.o  test2.o  test3.o

4. GNU 调试工具gdb

  • gdb程序调试的对象是可执行文件,而不是程序的源代码文件。
  • 如果要让产生的可执行文件可以用来调试,需在执行gcc指令编译程序时,加上-g参数,指定程序在编译时包含调试信息。
4.1 基本语法
gdb [filename]
4.2 gdb命令分类

file命令:装入想要调试的可执行文件。
命令格式:file 文件名

cd命令:改变工作目录。
命令格式:cd 目录名

pwd命令:返回当前工作目录。

list命令:列出正在调试的应用程序的源代码。
命令格式1:List,输出从上次调用list命令开始往后的10行程序代码。
命令格式2:list -,输出从上次调用list命令开始往前的10行程序代码。
命令格式3:list n,输出第n行附近的10行程序代码。
命令格式4:list function,输出函数function前后的10行程序代码。

run命令:执行当前被调试的程序。如果程序有参数,可随后输入。
命令格式: run

kill命令:停止正在调试的应用程序。
命令格式: kill

break命令:设置断点。程序已被载入,并且当前没有运行。
命令格式1:break 行号,当前源文件的某一行上设置断点。
命令格式2:break 函数名,在函数入口设置断点。
命令格式3:break 文件名:行号,在另一文件的某一行上设置断点。

disable :让指定断点失效。使用格式:
命令格式1: disable 断点号列表

watch命令:设置监视点,监视表达式的变化,当表达式的值发生改变时会停止运行。
命令格式:watch 变量或表达式

awatch命令:设置读写监视点。当要监视的表达式被读或写时将应用程序挂起。它的语法与watch命令相同。

rwatch命令:设置读监视点,当监视表达式被读时将程序挂起,等侍调试。此命令的语法与watch相同。

next命令:执行下一条源代码,但是不进入函数内部。执行这个命令的前提是已经run,开始了代码的执行。
命令格式:next

step命令:执行下一条源代码,进入函数内部。执行这个命令的前提是已经用run开始执行代码。
命令格式:step

display命令:在应用程序每次停止运行时显示表达式的值。
命令格式: display 表达式

info break命令:显示当前断点列表,包括每个断点到达的次数
命令格式: info break

info files命令:显示调试文件的信息。
命令格式: info files

info func命令:显示所有的函数名。
命令格式: info func

info local命令:显示当前函数的所有局部变量的信息。
命令格式: info local

info prog命令:显示调试程序的执行状态。
命令格式: info prog

set :设置程序中变量的值。
命令格式: set 变量=表达式

where:查看调用堆栈信息。
命令格式: where

print命令;打印变量或表达式的值。
命令格式:print 变量或表达式

delete命令:删除断点。指定一个断点号码,则删除指定断点。不指定参数则删除所有的断点。
命令格式: delete 断点号

shell命令:执行Linux Shell命令。
命令格式: shell 命令

make命令:不退出gdb而重新编译生成可执行文件。
命令格式:make

quit命令:退出gdb。
命令格式:quit

5. Makefile

规则主要是描述哪些文件(称为target目标文件,不要和编译时产生的目标文件相混淆)是从哪些别的文件(称为dependency依赖文件)中产生的,以及用什么命令(command)来执行这个过程。

5.1 Makefile规则的一般形式
target:dependency dependency
	(tab)<command>

一个目标(target),即make最终需要创建的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如“clean”。
一个或多个依赖文件(dependency)列表,通常是编译目标文件所需要的其他文件。
一系列命今(command),是make执行的动作,通常是把指定的相关文件编译成目标文件的编译命令,每个命令占一行,且每个命令行的起始字符必须为TAB字符

#例
test:prog.o code.o
		gcc –o test prog.o code.o
 prog.o:prog.c prog.h code.h
		gcc –c prog.c –o prog.o
 code.o:code.c code.h
		gcc –c code.c –o code.o
 clean:
		rm –f *.o 

在Makefile中,可使用续行号(\)将一个单独的命令行延续成几行。但要注意在续行号(\)后面不能跟任何字符(包括空格和键)

  • 调用make命令可输入:# make target
  • target是Makefile文件中定义的目标之一,如果省略target,make就将生成Makefile文件中定义的第一个目标。
  • 对于上面Makefile的例子,单独的一个make命令等价于:# make test
    因为test是Makefile文件中定义的第一个目标,make首先将其读入,然后从第一行开始执行,把第一个目标test作为它的最终目标,所有后面的目标的更新都会影响到test的更新。
  • 第一条规则说明只要文件test的时间戳比文件prog.o或code.o中的任何一个旧,下一行的编译命令将会被执行。
  • 但是,在检查文件prog.o和code.o的时间戳之前,make会在下面的行中寻找以prog.o和code.o为目标的规则,在第三行中找到了关于prog.o的规则,该文件的依赖文件是prog.c、prog.h和code.h。同样,make会在后面的规则行中继续查找这些依赖文件的规则,如果找不到,则开始检查这些依赖文件的时间戳,如果这些文件中任何一个的时间戳比prog.o的新,make将执行“gcc
    –c prog.c –o prog.o”命令,更新prog.o文件。
  • 以同样的方法,接下来对文件code.o做类似的检查,依赖文件是code.c和code.h。当make执行完所有这些套嵌的规则后,make将处理最顶层的test规则。如果关于prog.o和code.o的两个规则中的任何一个被执行,至少其中一个.o目标文件就会比test新,那么就要执行test规则中的命令,因此make去执行gcc命令将prog.o和code.o连接成目标文件test。
  • 在上面Makefile的例子中,还定义了一个目标clean,它是Makefile中常用的一种专用目标,即删除所有的目标模块
5.2 make的工作过程
  • 首先make按顺序读取makefile中的规则,
  • 然后检查该规则中的依赖文件与目标文件的时间戳哪个更新
  • 如果目标文件的时问戳比依赖文件还早,就按规则中定义的命令更新目标文件。
  • 如果该规则中的依赖文件又是其他规则中的目标文件,那么依照规则链不断执行这个过程,直到Makefile文件的结束,至少可以找到一个不是规则生成的最终依赖文件,获得此文件的时间戳
  • 然后从下到上依照规则链执行目标文件的时间戳比此文件时间戳旧的规则,直到最顶层的规则.
  • 通过以上的分析过程,可以看到make的优点,因为.o目标文件依赖.c源文件,源码文件里一个简单改变都会造成那个文件被重新编译,并根据规则链依次由下到上执行编译过程,直到最终的可执行文件被重新连接。
  • 例如,当改变一个头文件的时候,由于所有的依赖关系都在Makefile里,因此不再需要记住依赖此头文件的所有源码文件,make可以自动的重新编译所有那些因依赖这个头文件而改变了的源码文件,如果需要,再进行重新连接
2020-02-09 20:05:38 yuupengsun 阅读数 81
  • Linux系统编程第06期:从零实现一个shell解释器

    在Linux环境下,shell是一个位于操作系统和用户应用程序之间的工具,我们在shell终端下敲入命令并运行,或者直接运行 一个脚本文件,这背后都是shell在帮助我们解析命令并创建一个个子进程去执行。为了更深一层去探寻shell背后的机制原理、加深对Linux系统的理解, 本课程将带领大家,从零开始一步一步实现一个shell解释器:wsh,主要实现以下功能: * 可以在shell交互窗口中执行用于输入的shell命令 * 实现shell的内建命令:cd、exit、export等 * 支持管道命令 | * 支持进程的后台执行 * 支持脚本的解析和运行 * 支持脚本简单的if-else控制语法 * 支持信号的处理操作

    353 人正在学习 去看看 王利涛

env  查看环境变量,查看所有的环境变量
echo  $PATH  之查看PATH的环境变量

当控制台输入命令的时候,则先会取PATH下查找命令bin文件,如果有则执行,如果没有则会报错

更改环境变量值:


方法1:一次性更改

关闭终端则会失去作用,当重新开启终端后会失去作用
export  PATH = $PATH:/home/linux/文件夹1
PATH=$PATH  表示给新的PATH 增加之前本来就有的PATH值。
冒号之后“:”则是需要添加的路径,而且是绝对路径

方法2:永久性


/etc/profile    
“export  PATH = $PATH:/home/linux/文件夹1”添加至profile文件的末尾,则就会永久的修改环境变量
sudo vim  修改后保存执行source  /etc/profile  后才会立即生效,而且是每次开启终端Terminal需要再次执行source  /etc/profile  后才会再次生效。如果需要永久生效,则需要重新启动终端机“reboot”

2018-11-15 11:00:04 boice_girl 阅读数 313
  • Linux系统编程第06期:从零实现一个shell解释器

    在Linux环境下,shell是一个位于操作系统和用户应用程序之间的工具,我们在shell终端下敲入命令并运行,或者直接运行 一个脚本文件,这背后都是shell在帮助我们解析命令并创建一个个子进程去执行。为了更深一层去探寻shell背后的机制原理、加深对Linux系统的理解, 本课程将带领大家,从零开始一步一步实现一个shell解释器:wsh,主要实现以下功能: * 可以在shell交互窗口中执行用于输入的shell命令 * 实现shell的内建命令:cd、exit、export等 * 支持管道命令 | * 支持进程的后台执行 * 支持脚本的解析和运行 * 支持脚本简单的if-else控制语法 * 支持信号的处理操作

    353 人正在学习 去看看 王利涛

1. set

Linux set命令用来设置 shell ,设置使用shell的执行方式。
参数说明

  • -a  标示已修改的变量,以供输出至环境变量。
  • -b  使被中止的后台程序立刻回报执行状态。
  • -C  转向所产生的文件无法覆盖已存在的文件。
  • -d  Shell预设会用杂凑表记忆使用过的指令,以加速指令的执行。使用-d参数可取消。
  • -e  若指令传回值不等于0,则立即退出shell。
  • -f  取消使用通配符。
  • -h  自动记录函数的所在位置。
  • -H Shell  可利用"!"加<指令编号>的方式来执行history中记录的指令。
  • -k  指令所给的参数都会被视为此指令的环境变量。
  • -l  记录for循环的变量名称。
  • -m  使用监视模式。
  • -n  只读取指令,而不实际执行。
  • -p  启动优先顺序模式。
  • -P  启动-P参数后,执行指令时,会以实际的文件或目录来取代符号连接。
  • -t  执行完随后的指令,即退出shell。
  • -u  当执行时使用到未定义过的变量,则显示错误信息。
  • -v  显示shell所读取的输入值。
  • -x  执行指令后,会先显示该指令及所下的参数。
  • +<参数>  取消某个set曾启动的参数。
    set -xset +x可以配套使用,显示一段代码的运行情况,在set命令之后执行的每一条命令以及加载命令行中的任何参数都会显示出来,每一行都会加上加号(+),提示它是跟踪输出的标识。

2. export

Linux export命令用于设置或显示环境变量。
语法: export [-fnp][变量名称]=[变量设置值]
参数说明:

  • -f  代表[变量名称]中为函数名称。
  • -n  删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
  • -p  列出所有的shell赋予程序的环境变量。

3.shell 数组

  • 获取数组的元素
    使用@ 或 * 可以获取数组中的所有元素
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"

输出的结果为

$ chmod +x test.sh 
$ ./test.sh
数组的元素为: A B C D
数组的元素为: A B C D
  • 获取数组的长度
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"

输出的结果为:

$ chmod +x test.sh 
$ ./test.sh
数组元素个数为: 4
数组元素个数为: 4

4.case … esac

与其他语言中的 switch … case 语句类似,是一种多分支选择结构。

5.tee

Linux tee命令用于读取标准输入的数据,并将其内容输出成文件。
tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。
参数:

  • -a或–append  附加到既有文件的后面,而非覆盖它.
  • -i或–ignore-interrupts  忽略中断信号。
  • –help  在线帮助。
  • –version  显示版本信息。

6.time

一个程序在运行时使用的系统资源通常包括CPU、内存和I/O等;
CPU资源的统计包括实际使用时间(real time)、用户态使用时间(the process spent in user mode)、内核态使用时间(the process spent in kernel mode)。
time 它可以为一段脚本或一个程序的执行计时。

Linux命令文档

阅读数 170

Linux Shell脚本

阅读数 40

没有更多推荐了,返回首页