01Linux系统编程常用工具补充(接上篇)
文章目录
- 一、静态库和动态库
- 1.1 静态库
- 1.2 动态库
- 二、gdb调试
- 2.1 作用
- 2.2 调试过程及步骤
- 三、项目管理工具(makefile)
- 3.1 作用
- 3.2 编写“规则”
- ①基本编译
- ②按编译步骤编译
- ③makefile 中的变量和使用
- ④伪目标
- ⑤项目级makefile
接上篇:00Linux系统编程之你需要知道的
补充“零食”:主函数(main)传参
int main(int argc, char *argv[]);
int argc
为传入参数的个数
char *argv[]
为传入参数的内容
argv[0]
为程序运行指令,即./a.out
/./文件名
举个例子
#include <stdio.h> #include <stdlib.h>int main(int argc,char *argv[]) {int num1 = atoi(argv[1]);int num2 = atoi(argv[3]);char order = *argv[2];switch(order){case '+':printf("%d + %d = %d",num1,num2,num1+num2);break;case '-':printf("%d - %d = %d",num1,num2,num1-num2);break;case '*':printf("%d * %d = %d",num1,num2,num1*num2);break;case '/':printf("%d / %d = %d",num1,num2,num1/num2);break;}printf("\n");return 0; }
一、静态库和动态库
库文件作用:保护源代码、方便移植
1.1 静态库
- 特点
以空间换时间 。封装后的静态库文件,仍然在项目目录中,占用项目包空间,但是不用去其他地方查找改库文件,节省时间。
- 封装过程
①把所有的.c 文件编译成.o 文件,除了 main.c
gcc -c xx.c -o xx.o
.c文件和.h文件成对存在。
编译.c文件时,需包含.h文件
gcc -c xx.c -o xx.o -I .h文件所在路径
②把所有的.o 文件,封装成静态库文件
ar -rc -o 静态库文件名 *.o
静态库文件名的命名特点:
库标识+库名+静态库标识(.a)
//举个栗子 libcal.a 库标识 lib 库名 cal(可改) 静态库标识 .a
③编译验证库文件是否可用
1.2 动态库
- 特点
以时间换空间 。编译时需要从系统库目录中查找动态库文件,浪费编译时间,但是节省项目包大小。
- 封装过程
①把所有的.c 文件编译成.o 文件,除了 main.c
注意细节同静态库封装
②把所有的.o 文件,封装成动态库文件
gcc -shared -fpic -o 动态库文件名 *.o
动态库文件名的命名特点:
库标识+库名+动态库标识(.so)
③把封装后的动态库文件,剪切到系统库文件==(/lib 或/usr/lib)==中
sudo mv 动态库文件名 /lib
④编译验证动态库文件是否可用
gcc src/main.c -lcal -o output/main -I include/
默认从系统库文件中找库名进行编译
二、gdb调试
2.1 作用
gdb 是开发和调试底层程序、系统软件的重要工具,尤其在没有图形化调试环境的场景下(如服务器端开发、嵌入式系统)发挥关键作用。
通过调试继续手动执行代码,从而找到代码问题,及时修改代码。
2.2 调试过程及步骤
- 调试过程
①测试
找出程序中存在的缺陷或错误
②固化
让程序的错误重现
③定位
确定相关的代码行
④纠正
修改代码纠正错误
⑤验证
确定修改解决了问题
实际操作。
- 调试步骤
- 生成可调试的可执行程序
gcc -g 程序文件 -o 生成文件
- 进入调试界面
gdb 可调试的可执行文件
- 查看代码
list
默认显示10行代码。
l 行号
显示该行号上下 10 行代码。
- 设置断点(break/b)
阻止程序自动向下进行,进入手动执行
b 行号
设置 该行 为断点。
info b
查看断点详细信息。
delete 断点编号
删除断点
- 运行程序
run
程序先自动运行,直到断点阻止。
注意:调试时必须设置断点,若无断点,程序瞬间就执行完了,什么信息也看不到
n
手动向下运行,遇到函数,不会进入到函数中运行,直接得到函数的执行结果。
s
手动向下运行,遇到函数,会进入到函数中一步一步运行。
print(p) 变量名
打印变量信息
cont(c)
跳过断点继续自动向下执行
quit
退出 gdb 调试
三、项目管理工具(makefile)
3.1 作用
管理项目编译。
使用 make 直接自动编译
3.2 编写“规则”
makefile 的执行需要使用 make 命令。
sudo apt install make
安装 make
make 指令默认在当前目录下查找 makefile 或 Makefile 文件执行。其他名字需要使用
make -f filename
目标:依赖指令
指令需要使用 table 缩进
①基本编译
②按编译步骤编译
makefile文件,注释前用
#
#第一个目标为主目标
#下边的目标是根据上一个目标的依赖来执行的,若上一个目标的依赖已存在,则下面不会执行。
main:a.ogcc a.o -o main
a.o:a.sas a.s -o a.o
a.s:a.igcc -S a.i -o a.s
a.i:a.cgcc -E a.c -o a.i
③makefile 中的变量和使用
#定义变量
CC = gcc
#使用变量
main:a.o$(CC) a.o -o main
a.o:a.sas a.s -o a.o
a.s:a.i$(CC) -S a.i -o a.s
a.i:a.c$(CC) -E a.c -o a.i
特殊变量:
$<
第一个依赖的文件。
$@
目标文件。
$^
所有的依赖文件。
#定义变量
CC = gcc
#使用变量
main:a.o$(CC) $^ -o $@
a.o:a.sas $^ -o $@
a.s:a.i$(CC) -S $^ -o $@
a.i:a.c$(CC) -E $^ -o $@
④伪目标
没有依赖的目标
clean:rm a.i a.o a.s main
make clean
⑤项目级makefile
$(wildcard PATTERN)
-
函数名称:
wildcard
获取匹配模式文件名函数 -
函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。
-
返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。
-
函数说明:“PATTERN”使用 shell 可识别的通配符,包括“?”(单字符)、“*”(多字符)等。
#举个栗子
#获取到指定目录下的.c文件
SRCPATH=$(wildcard src/*.c)
$(notdir NAMES…)
-
函数名称:
notdir
取文件名函数 -
函数功能:从文件名序列“NAMES…”中取出非目录部分。目录部分是指最后一个斜线(“/”)(包括斜线)之前的部分。删除所有文件名中的目录部分,只保留非目录部分。
-
返回值:文件名序列“NAMES…”中每一个文件的非目录部分。
-
函数说明:如果“NAMES…”中存在不包含斜线的文件名,则不改变这个文件名。以反斜线结尾的文件名,是用空串代替
#举个栗子
#获取到指定目录下的.c文件
SRCPATH=$(wildcard src/*.c)
#剔除目录名称,只保留文件名
NOTSRCPATH=$(notdir $(SRCPATH))
$(patsubst PATTERN,REPLACEMENT,TEXT)
-
函数名称:模式替换函数—patsubst。
-
函数功能:搜 索 “TEXT” 中以空格分开的单词,将 否 符 合 模 式“TATTERN”替换为“REPLACEMENT”。参数“PATTERN”中可以使用模式通配符 “%” 来代表一个单词中的若干字符 。 如 果 参 数“REPLACEMENT”中也包含一个“%”,那么“REPLACEMENT”中的“%”将是“TATTERN”中的那个“%”所代表的字符串。在“TATTERN”和“REPLACEMENT”中,只有第一个“%”被作为模式字符来处理,之后出现的不再作模式字符(作为一个字符)。在参数中如果需要将第一个出现的“%”作为字符本身而不作为模式字符时,可使用反斜杠“\”进行转义处理。
-
返回值:替换后的新字符串。
-
函数说明:参数“TEXT”单词之间的多个空格在处理时被合并为一个空格,并忽略前导和结尾空格。
#举个栗子
#获取到指定目录下的.c文件
SRCPATH=$(wildcard src/*.c)
#剔除目录名称,只保留文件名
NOTSRCPATH=$(notdir $(SRCPATH))
#把.c文件生成需要的对应的.o文件名称
LIBPATH = $(patsubst %.c,src/%.o,$(NOTSRCPATH))