Linux常见工具使用

🎬 个人主页Vect个人主页

🎬 GitHubVect的代码仓库
🔥 个人专栏 : 《数据结构与算法》《C++学习之旅》《Linux

⛺️Per aspera ad astra.



文章目录

Makefile

0. 简单代码演示

cpp 复制代码
// add.h
#pragma once 

int add(int a, int b);
cpp 复制代码
// add.cpp

#include "add.h"

int add(int a, int b) { return a + b;}
cpp 复制代码
// main.cpp

#include <iostream>
#include "add.h"

int main(){
    std::cout<<add(1,2)<<std::endl;
    return 0;
}

1. Makefile结构及规则

这里先提前有个认知:

  • Makefile是文件
  • make是指令

先来看代码,然后解读:

bash 复制代码
# 变量定义部分
SRC = main.cpp add.cpp 
OBJ = $(SRC:.cpp=.o)
BIN = myapp

# 默认目标
$(BIN): $(OBJ)
	g++ -o $@ $^
	
# 编译目标
%.o: %.cpp
	g++ -c $< -o $@
	
# 清理目标
.PHONY: clean
clean:
	rm -f $(OBJ) $(BIN)
	

变量定义部分

SRC = main.cpp add.cpp

  • 作用:定义源文件变量,包含所有.cpp的源文件
  • 解释:SRC是一个包含需要编译的源文件的列表

OBJ = $(SRC:.cpp=.o)

  • 作用:通过模式替换,将SRC中的.cpp全部转换成.o文件
  • 解释:$(VAR)用来引用一个变量的值,$(SRC:.cpp=.o)利用替换模式 得到OBJ = main.o add.o

BIN = myapp

  • 作用:定义最终生成的目标文件名(最后的可执行文件)

默认目标部分

$(BIN):$(OBJ)

  • 作用:表示目标$(BIN) 依赖于$(OBJ)中的main.o add.o

g++ -o $@ $^

  • 作用:使用g++.o文件链接成最终可执行文件myapp
  • 解释:
    • $@:代表当前规则中的目标文件,这里是$(BIN)
    • $^:代表所有的依赖文件(去除重复的),这里是$(OBJ)

编译目标部分

%.o: %.cpp

  • 作用:表示一条通用规则,告诉make如何将.cpp文件编译成.o文件
  • 解释:%是通配符,代表一个任意的字符序列,这里表示会匹配所有的.cpp文件,将它们全部编译为对应的.o文件

g++ -c &< -o $@

  • 作用:使用g++.cpp文件编译成.o文件
  • 解释:
    • $<:代表当前规则中的第一个依赖文件,在这里就是 .cpp 文件
    • $@:表示当前规则中的目标文件,在这里是 .o 文件

清理目标部分

.PHONY: clean

  • 作用:声明clean是一个伪目标,而不是文件名
  • 解释:make 会认为 clean 是一个任务,而不是文件,因此即使当前目录下存在名为 clean 的文件,make 也会执行 clean 规则的命令

clean: rm -f $(OBJ) $(BIN)

  • 作用:clean 目标的命令部分,删除所有生成的目标文件和最终的可执行文件。

2. 过程推导

目标文件.o和依赖关系

  • main.o依赖于main.cpp
  • add.o依赖于add.cpp

在Makefile中,$OBJ 是要生成的目标文件,它的生成依赖于.cpp文件

规则推导过程

make会从默认目标 myapp开始,通过依赖关系逐步推导出需要做的工作

  1. make看到myapp

    myapp的形成依赖于main.oadd.omake会从main.oadd.o开始推导

  2. 生成main.o

    main.o的生成又依赖于main.cpp,所以make会执行:g++ -c main.cpp -o main.o

  3. 生成add.o

    同理add.o的生成依赖于add.cpp,所以make会执行: g++ -c add.cpp -o add.o

  4. 链接成myapp

    当生成了main.oadd.omake会执行:g++ -o mayapp main.o add.o

推导是一个出栈入栈的过程

  • 出栈: make开始时看到myapp,出栈myapp,处理它的依赖main.oadd.o
  • **入栈:**当 main.oadd.o 处理完后,它们的目标文件会 入栈 ,然后 make 执行生成 myapp 的命令

我们梳理清楚依赖链:

目标 直接依赖 构建规则
myapp main.o add.o g++ -o myapp main.o add.o
main.o main.cpp g++ -c main.cpp -o main.o
add.o add.cpp g++ -c add.cpp -o add.o
clean 伪目标 rm -f main.o add.o myapp

时间戳

make在做依赖关系推导的时候,会用时间戳来决定哪些目标需要重新构建

时间戳的作用

make会比较每个目标文件和它的依赖文件的时间戳

  • 如果依赖文件比目标文件新,make会重新构建目标文件
  • 如果目标文件存在且没有被更新,make会跳过编译过程
bash 复制代码
[vect@VM-0-11-centos make_file]$ stat main.cpp
  File: 'main.cpp'
  Size: 102       	Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d	Inode: 1051720     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1002/    vect)   Gid: ( 1002/    vect)
Access: 2025-12-14 20:12:03.883557588 +0800
Modify: 2025-12-14 20:12:01.955499062 +0800
Change: 2025-12-14 20:12:01.955499062 +0800
 Birth: -

看一下三种时间:

  • Acesstime:访问时间,文件内容被读取/访问的时间
  • Modifytime:修改时间,文件时间内容被修改的时间(文件大小、内容变化)
  • Changetime:状态改变时间,文件**元数据(属性)**改变的时间(文件属性)

过程演示:

  1. 第一次运行make

    make的行为:

    bash 复制代码
    [vect@VM-0-11-centos make_file]$ make
    g++ -c main.cpp -o main.o
    g++ -c add.cpp -o add.o
    g++ -o myapp main.o add.o

    此时目标文件和可执行文件都生成了,时间戳被记录

  2. 修改源文件并运行make

    假设修改了 add.cpp 文件中的代码,例如:

    cpp 复制代码
    int add(int a, int b) {
        return a * b;  // 修改了加法为乘法
    }

    现在,make会根据文件时间戳决定是否重新编译:

    • main.o时间戳未变化,main.cpp不重新编译
    • add.o文件的时间戳比add.cpp新,make会发现add.o的依赖文件add.cpp发生变化

    运行指令得到:

    bash 复制代码
    [vect@VM-0-11-centos make_file]$ make
    g++ -c add.cpp -o add.o
    g++ -o myapp main.o add.o
  3. 不做任何修改,直接运行make

    bash 复制代码
    [vect@VM-0-11-centos make_file]$ make
    make: `myapp' is up to date.

总结:

  1. 目标文件不存在 :如果目标文件(.o)或依赖文件(.cpp)不存在,make 会强制编译并生成目标文件。

  2. 依赖文件更新 :如果依赖文件的时间戳比目标文件更新,make 会重新编译依赖文件并更新目标文件。

  3. 无更新时跳过编译 :如果目标文件和依赖文件的时间戳都没有变化,make 会跳过编译过程,避免重复工作。

伪目标

伪目标:没有对应文件的目标文件,用来执行命令而不关心文件的存在

伪目标不会检查时间戳,每次执行都会运行相关指令

bash 复制代码
.PHONY: clean

clean:
    rm -f $(OBJ) $(BIN)

.PHONY 告诉 make clean 是伪目标,即使当前目录下有一个 clean 文件,make 也不会认为它是一个文件,而是会执行 rm 命令

gdb调试

gdb使用须知

程序发布方式:

  1. debug版本:程序本身会被加入更多调试信息,便于调试
  2. release版本:不添加任何调试信息,不可调试

在Linux下,gcc/g++默认生成的可执行程序是release版本,若想生成debug版本,就需要加上-g选项

对同一代码分贝生成release版本和debug版本的可执行程序,可以看到debug版本要更大,原因是debug版本包含了更多的调试信息

gdb命令汇总

【进入gdb】

gdb 二进制文件名

【退出】

ctrl+dquit调试命令

【常见命令】

  • list/l:列出源代码,从上次位置开始,每次列10行

  • list/l 函数名:列出指定函数的源代码

  • list/l 文件名:行号:列出指定文件的源代码

  • run/r:从程序开始连续执行

  • next/n:单步执行,不进入函数内部,相当于逐过程F10

  • step/s:单步执行,进入函数内部,相当于逐语句F11

  • break/b 文件名:行号:指定行号打断点,b 10 b test.c:10

  • info break/b:查看当前所有断点信息

    这里显示断点编号和断点类型以及其他信息

  • finish:执行到当前函数返回,然后停止

  • print/p 表达式:打印表达式的值

  • p 变量:打印指定变量的值

  • set var 变量=值:修改变量的值

  • continue/c:从当前位置开始连续执行程序

  • delete/d breakpoints:删除所有断点

  • delete/d breakpoints n:删除序号为n的断点

  • disable breakpoints:禁用所有断点

  • enable breakpoints: 启用所有断点

  • info/i breakpoints:查看当前设置的断点列表

  • display 变量名:跟踪显示指定变量的值

  • undisplay 编号:取消对指定编号的变量的跟踪显示

  • until x:执行到指定行号

  • backtrace/bc:查看当前执行栈的各级函数调用及参数

  • info/i locals:查看当前栈帧的局部变量值

vim的使用

vim是一种多模式编辑器,总共有12种模式,本文只详细讲解三种常见模式:命令模式 插入模式 第行模式

  • **命令模式:**控制光标的移动,进行字符或行的删除,移动复制某区域内容
  • **插入模式:**文本编辑
  • 底行模式: 文本保存、退出、文件替换、查找文本内容、执行命令
  • 替换模式: 文本替换
  • 视图模式:

1. 命令模式操作

  • 进入vim

    vim file,如果文件不存在就会自动创建并进入vim编辑器页面,默认进入命令模式

  • 命令模式->插入模式

    输入a:光标后移一位进入编辑

    输入o:光标另起一行到行首进入编辑

    输入i:光标位置进入编辑

  • 命令模式->底行模式

    shift+; 就是输入:

  • 退出vim并保存文件: 从命令模式转到底行模式

    w:保存当前文件

    wq:保存并退出

    q!:不保存强制退出

  • 复制 注意:n代表数字

    n+yy:光标所在行开始,复制n行

    n+p:从光标所在行下一行行首开始,粘贴n次

    u:撤销上一次操作

    ctrl+r:取消撤销

  • 移动光标

    shift+g:即G,定位到文本末尾

    gg:定位到文本开头

    n+shift+g:定位到第n行

    h j k l:← ↓ ↑ →移动光标

    $:定位到本行末尾

    ^:定位到本行开头

    w:光标跳到下一个字的开头

    b:光标跳到上一个字的开头

  • 删除

    n+x:光标所在位置开始向后删除n个字符

    n+X:光标所在位置开始向前删除n个字符

    dd:删除光标所在行

  • 替换

    n+r+输入字符:从光标所在位置开始,用n个输入字符替换原字符

  • 更改

    shift+~:光标所在位置大小写替换

2. 底行模式操作

进入底行模式之前,先按esc键确定在命令模式下,再按:进入第行模式

  • 列出行号

    set nu:输入set nu,会在文件中每一行前面列出行号

    set nonu:取消行号

  • 查找

    /关键字:先按/,再输入想查找的内容,按n会跳转到下一个匹配的

    ?关键字:先按/,再输入想查找的内容,按n会跳转到上一个匹配的

  • 保存文件

    w

  • 离开vim

    q

    q!

3. 视图模式和替换模式

  • 从命令模式按shift+r会进入替换模式,此时就可以进行文本、字符替换操作

  • 从命令模式按ctrl+v会进入视图模式

    hjkl会进行区域选择,按I进入插入模式,然后按输入//后立马按ESC回到命令模式,就可以实现批量注释

4. 总结

相关推荐
加成BUFF2 小时前
树莓派安装下载及远程连接(共用手机热点)(SSH)(VNC)
linux·计算机·ssh·bash·树莓派·vnc
wanhengidc2 小时前
裸金属服务器都有哪些优势?
运维·服务器·安全·智能手机·生活
Jamesvalley2 小时前
【centos】安装python3.12
linux·运维·centos
凯子坚持 c2 小时前
Redis 数据库的服务器部署与 MCP 智能化交互深度实践指南
服务器·数据库·redis
肉清3 小时前
linux自用命令
linux·服务器·前端
Xの哲學3 小时前
Linux链路聚合深度解析: 从概念到内核实现
linux·服务器·算法·架构·边缘计算
wanhengidc3 小时前
具有ARM架构云手机的功能
运维·服务器·arm开发·科技·智能手机·云计算
wanhengidc3 小时前
巨 椰 云手机离线多开
运维·服务器·科技·智能手机·云计算
代码游侠3 小时前
应用——管道与文件描述符
linux·服务器·c语言·学习·算法