【Linux篇】提高效率,解决一切问题:Linux 开发者的秘密武器(中篇)

接上篇 ->【Linux篇】让开发事半功倍:Linux 开发工具的实战指南(上篇):本篇博客本文介绍了在 Linux 环境中,如何使用软件包管理器、Vim 编辑器、GCC 编译器以及动态与静态库的相关命令和操作。首先,通过软件包管理器(如APT)进行软件包的安装、卸载和更新,帮助简化软件管理过程。然后,详细讲解了 Vim 编辑器的三种模式和基本操作,提升编辑效率。接着,解释了 GCC 编译器的编译流程、常用选项和动态、静态链接的区别。最后,介绍了如何使用 ldd 命令查看可执行文件或库文件的依赖关系,帮助开发人员有效管理和调试系统库。请跟随小编的步伐,一起进入学习之旅。

一. 自动化构建 - make/makefile

1.1 make的背景与历史

  • 起源:

make 最早由 Stuart Feldman 在1976年开发,目的是简化编译和链接过程。它最初是为了解决在大型项目中重复构建的问题,通过自动化构建流程来减少开发人员的工作量。

  • 功能:

make 通过检查文件的时间戳(如源文件和目标文件),只重新构建那些需要更新的部分。这样就避免了不必要的重新编译,节省了大量时间,尤其是在大型项目中。

它使用 规则(rules) 来指定哪些文件需要被编译或构建,以及如何编译这些文件。一个典型的规则由以下几部分组成:

  1. 目标文件(target):最终输出的文件(比如一个可执行文件)。
  2. 依赖文件(dependencies):构建目标所依赖的源文件或其他中间文件。
  3. 命令(commands):构建目标所需要执行的操作,如编译命令。

Makefile:

Makefile 是 make 的配置文件,包含了一系列规则和命令。它基本上是告诉 make 如何构建或更新一个项目。Makefile 通常包括:

  1. 目标:需要生成的文件。
  2. 依赖项:目标所依赖的文件。
  3. 构建命令:生成目标所需要执行的命令。

1.2 make/makefile 基本使用

示例代码:

#include <stdio.h>
int main()
{
printf(“hello Makefile!\n”);
return 0;
}

Makefile文件:

扫描二维码关注公众号,回复: 17592555 查看本文章

mytest:mytest.c
gcc -o mytest mytest.c
.PHONY:clean
clean:
rm -f mytest

核心思想:

  • 依赖关系:mytest的形成依赖于mytest.c
  • 依赖方法: gcc -o mytest mytestc ,就是上述的依赖关系
  • 项目清理:make会自下而上扫描,形成一个目标文件,除非下面的目标文件与第一个目标文件有关联,上述clean的目标文件,设置为伪目标,用.PHONY修饰,它的特性总是被执行。简单点说就是可以重复执行,反之没有被修饰会报错: make: ‘mytest’ is up to date.

问题1:为什么make后不能再编译

make
gcc test.c -o mytest
wch_1@hcss-ecs-2ce4:~/114/code/lesson2$ ll
total 28
-rw-rw-r-- 1 wch_1 wch_1 73 Mar 27 21:02 Makefile
-rwxrwxr-x 1 wch_1 wch_1 16696 Mar 27 21:02 mytest
-rw-rw-r-- 1 wch_1 wch_1 237 Mar 27 20:50 test.c
wch_1@hcss-ecs-2ce4:~/114/code/lesson2$ make
make: ‘mytest’ is up to date.

  • 编译器如何知道源文件需不需要重新编译

通过文件的属性创建与更改时间,发现不同就编译,反之不编译。

主要是为了提高编译效率!!!

结论:.PHONY:让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐

1.2.1 推导过程


在底行模式下,输入make命令后,make大致工作流程如下:

  1. 读取 Makefile

make 读取当前目录中的 Makefile(或指定的其他文件)。解析 Makefile 中的规则和命令。

  1. 检查目标文件

如果没有指定目标,默认执行 Makefile 中的第一个目标,通常是 all。

如果指定了目标,如 make ,make 会寻找与该目标匹配的规则。

  1. 依赖关系解析

对每个目标文件,make 会检查其依赖项。

比较目标文件的时间戳与依赖项的时间戳,确定是否需要重新构建。

如果目标文件的时间戳较旧,表示目标需要更新。

如果目标文件是最新的,且其依赖文件没有变化,make 会跳过该目标。

  1. 执行构建命令

如果目标需要更新,make 会执行规则中的命令。命令通常是编译或链接操作。

每个命令在单独的 shell 环境中执行。

  1. 递归构建

make 会递归检查目标的依赖项。如果某个依赖需要更新,make 会继续处理其依赖项并执行相应命令。

例如,若目标依赖 .o 文件,则 make 会先编译这些 .o 文件,再链接生成最终目标。

  1. 构建完成

当所有目标文件和依赖项都构建完成时,最终目标文件(如可执行文件)会生成。

  1. 清理操作

若 Makefile 中定义了 clean 目标,执行 make clean 可以删除所有生成的中间文件(如 .o 文件和可执行文件)以便重新构建。

1.3 适度扩展语法

BIN=proc.exe # 定义变量
CC=gcc
#SRC=KaTeX parse error: Expected 'EOF', got '#' at position 16: (shell ls *.c) #̲ 采⽤shell命令⾏⽅式,获…(wildcard *.c) # 或者使⽤ wildcard 函数,获取当前所有.c⽂件名
OBJ=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表
LFLAGS=-o # 链接选项
FLAGS=-c # 编译选项
RM=rm -f # 引⼊命令
( B I N ) : (BIN): (BIN):(OBJ)
@$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名。 $^: 代表依赖⽂件列表
@echo "linking … $^ to @ " 名 . o @ @" %.o:%.c # %.c 展开当前⽬录下所有的.c。 %.o: 同时展开同 名.o @ @".o@(CC) $(FLAGS) $< # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。
@echo “compling … $< to $@” # @:不回显命令
.PHONY:clean
clean:
$(RM) $(OBJ) $(BIN) # $(RM): 替换,⽤变量内容替换它
.PHONY:test
test:
@echo $(SRC)
@echo $(OBJ)

二. 回车与换行概念

实现本程序,需要额外大致了解一下下面的概念

2.1 回车与换行

回车 (\r):

  • 回车将光标移动到当前行的开头。
  • 它不会换到下一行,只是将光标移到当前行的最左侧。

换行 (\n):

  • 换行将光标移动到下一行的开头。
  • 它通常用来在文本中创建新的行。

示例:

  1. 回车的效果:

Hello, world!\rGoodbye

输出结果:

Goodbye, world!

在这个例子中,Hello, world! 被回车符号(\r)覆盖,光标回到行首,显示了 Goodbye。

  1. 换行的效果:

Hello, world!\nGoodbye

输出结果:

Hello, world!
Goodbye

这里,\n 创建了一个新的行,Goodbye 出现在下一行。

  1. 回车与换行组合的效果(Windows):

Hello, world!\r\nGoodbye

输出结果:

Goodbye
world!

这会把光标移到行首并换行,Goodbye 会出现在新的一行。

总结:

回车 (\r):光标移到当前行的开头。

换行 (\n):光标移到下一行的开头。

2.2 行缓冲区

2.2.1 什么是行缓冲区

行缓冲区(Line Buffering)是指在处理输入/输出时,数据以一行一行的方式进行缓冲。当缓冲区中积累了完整的一行数据时,才会将数据从缓冲区中处理或输出。

  • 具体定义:

行缓冲区的工作方式是,每当输入或输出到达换行符(如 \n)时,系统才会将该行数据传递给程序或设备。这种方式通常在处理文本输入输出时比较常见,尤其是与交互式输入输出操作(如命令行输入)相关。

行缓冲区的特点:

1 -> 输入缓冲区:当用户输入一行时,数据会先存储在缓冲区中,直到用户按下回车键(表示换行符 \n),系统才会将该行输入传递给程序进行处理。

2 -> 输出缓冲区:程序将数据写入缓冲区,直到遇到换行符(或缓冲区满)时,数据才会从缓冲区写到屏幕或文件。

行缓冲区的特点:

1 ->输入缓冲区:当用户输入一行时,数据会先存储在缓冲区中,直到用户按下回车键(表示换行符 \n),系统才会将该行输入传递给程序进行处理。

2 -> 输出缓冲区:程序将数据写入缓冲区,直到遇到换行符(或缓冲区满)时,数据才会从缓冲区写到屏幕或文件。

行缓冲区的优势:

<1> 提高效率:行缓冲区通常能减少每个字符的输入/输出操作次数,从而提高效率。程序可以一次性读取或写入整行数据。

<2>交互性:对交互式程序来说,行缓冲区能更好地处理逐行输入输出,使用户体验更加流畅。

行缓冲区的缺点:

延迟:如果程序需要更快的输入输出反应,行缓冲可能导致延迟,特别是在没有换行符时。

其他类型的缓冲:

字符缓冲(Character Buffering):每次输入一个字符就立即传递。

全缓冲(Full Buffering):只有缓冲区满时,才进行数据的读取或输出。

2.3 实现倒计时程序

#include <stdio.h>
#include <unistd.h>

int main()
{
    
    
int i = 10;
while(i >= 0)
{
    
    
printf("%-2d\r", i); // \n
fflush(stdout);
i--;
sleep(1);
}
printf("\n");
return 0;
}

三. 总结

本文介绍了 Linux 开发中的一些关键概念和工具,重点关注自动化构建、回车与换行概念以及行缓冲区。首先,make 工具帮助简化编译和链接过程,使用 Makefile 定义构建规则,避免不必要的重新编译,从而提高开发效率。回车与换行分别控制光标在当前行与下一行的位置。行缓冲区则通过在输入输出达到换行符时才传递数据,优化了效率并提升了交互性。通过理解这些工具和概念,开发者可以在 Linux 环境中更高效地进行开发和调试。

路虽远,行则将至;事虽难,做则必成

亲爱的读者们,下一篇文章再会!!! \color{Red}亲爱的读者们,下一篇文章再会!!! 亲爱的读者们,下一篇文章再会!!!

猜你喜欢

转载自blog.csdn.net/braveact/article/details/146536941
今日推荐