文章目录
- 前言
-
- 🍭一、Linux软件管理包apt(Ubuntu)
-
- [🍬1.1 什么是一软件包?](#🍬1.1 什么是一软件包?)
- [🍬1.2 关于rzsz](#🍬1.2 关于rzsz)
- [🍬1.3 查看软件包](#🍬1.3 查看软件包)
- [🍬1.4 如何安装软件](#🍬1.4 如何安装软件)
- [🍬1.5 如何卸载软件](#🍬1.5 如何卸载软件)
- 🍭二、Linux编译器-`gcc/g++`使用
-
- [🍫2.1 安装 `gcc/g++`](#🍫2.1 安装
gcc/g++
) - [🍫2.2 基本用法](#🍫2.2 基本用法)
- [🍫2.3 常用选项](#🍫2.3 常用选项)
- [🍫2.4 多文件编译](#🍫2.4 多文件编译)
- [🍫2.5 生成目标文件和链接](#🍫2.5 生成目标文件和链接)
- [🍫2.6 动态链接和静态链接](#🍫2.6 动态链接和静态链接)
- [🍫2.7 调试](#🍫2.7 调试)
- [🍫2.8 示例:编译 C/C++ 程序的完整流程](#🍫2.8 示例:编译 C/C++ 程序的完整流程)
- [🍫2.1 安装 `gcc/g++`](#🍫2.1 安装
- 🍭三、项目自动化构建工具`make/makefile`
-
- [🧁3.1 什么是 `make` 和 `Makefile`?](#🧁3.1 什么是
make
和Makefile
?) - [🧁3.2 Makefile 的基本语法](#🧁3.2 Makefile 的基本语法)
- [🧁3.3 使用 `make`](#🧁3.3 使用
make
) - [🧁3.4 Makefile 中的变量](#🧁3.4 Makefile 中的变量)
- [🧁3.5 Makefile 中的特殊符号和自动变量](#🧁3.5 Makefile 中的特殊符号和自动变量)
- [🧁3.6 Makefile 中的内置函数](#🧁3.6 Makefile 中的内置函数)
- [🧁3.7 Makefile 的伪目标](#🧁3.7 Makefile 的伪目标)
- [🧁3.1 什么是 `make` 和 `Makefile`?](#🧁3.1 什么是
- 🍭四、Linux调试器-`gdb`使用
-
- [🍮4.1 常用主要功能](#🍮4.1 常用主要功能)
- [🍮4.2 常用指令](#🍮4.2 常用指令)
- [🍮4.3 常用 GDB 指令表](#🍮4.3 常用 GDB 指令表)
- [🍮4.4 指令总结与使用场景](#🍮4.4 指令总结与使用场景)
- 结语
前言
Linux 是当今计算机领域最重要的操作系统之一,其强大的命令行工具和丰富的生态系统为开发者提供了极大的灵活性和效率。然而,对于新手和部分用户而言,如何使用这些工具高效管理软件、编译代码、自动化构建和调试程序仍然是一项挑战。这篇文章旨在为读者提供一站式的 Linux 工具指南,从软件包管理 (apt) 到编译器 (gcc/g++)、自动化构建工具 (make),再到调试器 (gdb),我们将以清晰、系统化的方式为您逐步解析这些工具的功能和使用方法。无论您是初学者还是有经验的开发者,这篇文章都能为您的 Linux 技能提升提供帮助。
🍭一、Linux软件管理包apt(Ubuntu)
🍬1.1 什么是一软件包?
软件包(Package)是一个包含软件程序及其相关文件的归档单元,用于在操作系统中安装、配置、更新和卸载软件。它通常包括程序的二进制文件、库文件、配置文件以及元数据(如依赖关系和版本信息)。
在 Linux 系统中,软件包是操作系统和用户软件的基础。通过软件包管理器,用户可以方便地管理和维护系统中的软件。
apt
(Advanced Package Tool)是 Ubuntu 和其他基于 Debian 的 Linux 发行版中用于管理软件包的工具。它是一个功能强大的命令行工具,用于安装、更新、搜索和删除软件包。
🍬1.2 关于rzsz
rz
和 sz
是 Linux 系统中的两个命令,用于通过 zmodem
协议在本地计算机和远程服务器之间上传和下载文件。它们通常用于终端工具,如 xterm
或基于 SSH 的终端模拟器(如 SecureCRT
和 xshell
)。
rz
(receive zmodem): 用于从本地上传文件到远程服务器。sz
(send zmodem): 用于从远程服务器下载文件到本地。
安装 rzsz
在大多数 Linux 系统中可以通过以下命令安装:
-
Debian/Ubuntu:
bashsudo apt install lrzsz
使用 rz
时,会弹出文件选择框选择上传的文件;使用 sz
时,会直接下载文件。
🍬1.3 查看软件包
在 Linux 系统中,您可以通过以下方法查看已安装的软件包或查找特定的软件包:
Ubuntu/Debian:
-
查看已安装的软件包:
bashdpkg -l
-
搜索特定的软件包:
bashdpkg -l | grep <package_name>
APT(适用于 Ubuntu/Debian):
bash
apt list --installed
🍬1.4 如何安装软件
使用 apt
安装:
bash
sudo apt install <package_name>
🍬1.5 如何卸载软件
-
使用
apt
卸载:bashsudo apt remove <package_name>
清理残留文件:
-
在 Ubuntu/Debian 中,可以使用以下命令清理配置文件:
bashsudo apt purge <package_name> sudo apt autoremove
删除源码安装的软件:
-
如果是通过源码安装,可以进入安装目录并运行:
bashsudo make uninstall
-
如果没有卸载脚本,需要手动删除安装文件。
🍭二、Linux编译器-gcc/g++
使用
在 Linux 系统中,gcc
和 g++
是常用的编译器,用于编译 C 和 C++ 程序。以下是 gcc
和 g++
的使用方法和一些常见选项的说明:
🍫2.1 安装 gcc/g++
如果系统中没有安装 gcc/g++
,可以通过包管理器进行安装:
-
在 Ubuntu/Debian 系列系统上:
bashsudo apt update sudo apt install build-essential
build-essential
包会安装gcc
,g++
和一些基本的构建工具。
🍫2.2 基本用法
编译 C 程序 (gcc
)
-
编译一个简单的 C 程序:
bashgcc -o output_file source.c
说明:
-o output_file
:指定输出的可执行文件名。source.c
:C 源文件。
-
示例:
bashgcc -o hello hello.c ./hello
编译 C++ 程序 (g++
)
-
编译一个简单的 C++ 程序:
bashg++ -o output_file source.cpp
-
示例:
bashg++ -o hello_cpp hello.cpp ./hello_cpp
🍫2.3 常用选项
选项 | 功能 |
---|---|
-o |
指定输出文件名。 |
-c |
只编译,不链接生成目标文件(.o 文件)。 |
-g |
生成调试信息,用于调试器(如 gdb )。 |
-Wall |
启用所有常见的编译警告,帮助发现潜在错误。 |
-O 或 -O2 |
优化代码,-O2 表示更高级的优化(还有 -O0 关闭优化,-O3 开启更激进的优化)。 |
-I |
指定包含文件目录,例如 -I/usr/include/custom 。 |
-L |
指定链接库路径,例如 -L/usr/lib 。 |
-l |
指定链接的库,例如 -lm 表示链接数学库 libm.so 。 |
-std |
指定标准版本,例如 -std=c99 (C99 标准)或 -std=c++11 (C++11 标准)。 |
-D |
定义宏,例如 -DDEBUG 在代码中定义 #define DEBUG 。 |
🍫2.4 多文件编译
在项目中通常会有多个源文件,需要一起编译:
bash
gcc -o output_file file1.c file2.c
示例:
gcc -o program main.c utils.c
对于 C++ 项目:
bash
g++ -o output_file file1.cpp file2.cpp
🍫2.5 生成目标文件和链接
步骤 1:生成目标文件(.o
文件)
bash
gcc -c file1.c
gcc -c file2.c
会生成 file1.o
和 file2.o
。
步骤 2:链接目标文件
bash
gcc -o output_file file1.o file2.o
同理,对于 C++ 文件:
bash
g++ -c file1.cpp
g++ -c file2.cpp
g++ -o output_file file1.o file2.o
🍫2.6 动态链接和静态链接
动态链接(默认)
动态链接会依赖动态库(如 .so
文件)。
bash
gcc -o output_file source.c -lm
示例:链接数学库 libm.so
。
静态链接
静态链接会将所需的库文件直接嵌入到生成的可执行文件中。
bash
gcc -o output_file source.c -static -lm
-static
表示使用静态链接。
🍫2.7 调试
编译时添加 -g
选项,生成包含调试信息的二进制文件:
bash
gcc -g -o debug_program program.c
使用 gdb
调试:
bash
gdb ./debug_program
🍫2.8 示例:编译 C/C++ 程序的完整流程
C 程序示例
-
源文件:
main.c
c#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
-
编译和运行:
bashgcc -Wall -o hello main.c ./hello
C++ 程序示例
-
源文件:
main.cpp
cpp#include <iostream> using namespace std; int main() { cout << "Hello, World!" << endl; return 0; }
-
编译和运行:
bashg++ -Wall -o hello_cpp main.cpp ./hello_cpp
🍭三、项目自动化构建工具make/makefile
🧁3.1 什么是 make
和 Makefile
?
make
是一个工具,用于根据指定的规则,自动化执行一系列命令(如编译代码)。Makefile
是一个文本文件,定义了构建项目的规则、依赖关系和命令。
核心思想:如果某个目标文件依赖的源文件发生了变化,就重新生成目标文件。
🧁3.2 Makefile 的基本语法
基本结构
makefile
目标: 依赖
命令
- 目标(target):最终生成的文件(如可执行文件)。
- 依赖(dependencies):目标文件所依赖的源文件或其他目标。
- 命令(commands) :为了生成目标而需要执行的命令(必须以 Tab 开头)。
示例
makefile
hello: hello.o utils.o
gcc -o hello hello.o utils.o
hello.o: hello.c
gcc -c hello.c
utils.o: utils.c
gcc -c utils.c
clean:
rm -f *.o hello
说明:
hello
是最终的可执行文件,依赖于hello.o
和utils.o
。- 如果
hello.c
或utils.c
修改了,则只会重新编译对应的.o
文件。 clean
是一个伪目标,用于清理构建产生的文件(没有依赖和目标文件)。
🧁3.3 使用 make
假设上面的 Makefile 保存为 Makefile
文件:
执行构建
bash
make
- 默认会执行第一个目标(
hello
)。 - 如果源文件没有变化,
make
会输出make: 'hello' is up to date.
。
执行清理
bash
make clean
- 执行
clean
目标的命令,删除.o
文件和可执行文件。
🧁3.4 Makefile 中的变量
为了减少重复,Makefile 支持变量定义和引用。
定义变量
makefile
CC = gcc
CFLAGS = -Wall -g
TARGET = hello
OBJS = hello.o utils.o
使用变量
makefile
$(变量名)
改进后的 Makefile
makefile
CC = gcc
CFLAGS = -Wall -g
TARGET = hello
OBJS = hello.o utils.o
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o $(TARGET)
说明:
$<
:表示第一个依赖项(如hello.c
)。$@
:表示当前目标(如hello.o
)。%.o: %.c
:通配规则,表示所有.c
文件生成对应的.o
文件。
🧁3.5 Makefile 中的特殊符号和自动变量
符号/变量 | 作用 |
---|---|
$@ |
当前目标的名字。 |
$^ |
所有依赖项的名字(去重)。 |
$< |
第一个依赖项的名字。 |
$? |
所有比目标文件更新的依赖项。 |
$(VAR) |
引用变量 VAR 。 |
🧁3.6 Makefile 中的内置函数
常用函数
函数 | 作用 |
---|---|
$(wildcard *.c) |
获取当前目录下所有 .c 文件。 |
$(patsubst %.c, %.o, $(SRC)) |
将变量 SRC 中的所有 .c 替换为 .o 。 |
$(shell 命令) |
执行 shell 命令并将输出存储到变量中。 |
示例
makefile
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
$(TARGET): $(OBJS)
$(CC) -o $@ $^
clean:
rm -f $(OBJS) $(TARGET)
🧁3.7 Makefile 的伪目标
伪目标是指不生成文件的目标,用于执行一些任务(如清理)。
定义伪目标
makefile
.PHONY: clean all
伪目标的作用:
- 避免和实际文件重名。
- 强制执行目标。
🍭四、Linux调试器-gdb
使用
GDB(GNU Debugger)是GNU项目开发的一款功能强大的调试工具,用于调试C、C++、Fortran等编程语言编写的程序。它是Linux系统下最常用的调试工具之一,可以帮助开发者定位程序中的错误和问题,从而提高代码的质量和开发效率。
🍮4.1 常用主要功能
- 运行程序 :
- 可以按用户指定的方式启动程序,设置参数和环境变量。
- 设置断点 :
- 用户可以在程序的特定位置(如函数或行号)设置断点,程序运行到断点时会暂停,方便检查当前状态。
- 单步执行 :
- 支持逐行或逐指令执行代码,便于分析程序逻辑和排查问题。
- 查看变量值 :
- 可以查看和修改内存中变量的值,帮助了解程序的运行状态。
🍮4.2 常用指令
我将以下面代码为例,为大家演示gdb的常用方法,以下是mycode的主要内容,并且以及生成了一个debug模式的可执行程序mycode
cpp
#include <iostream>
int AddTop(int top)
{
int res = 0;
for (int i = 1; i <= top; i++)
{
res += i;
}
return res;
}
int main()
{
std::cout << "Debug begin" << std::endl;
int top = 100;
int sum = AddTop(top);
std::cout << "sum: " << sum << std::endl;
std::cout << "Debug end" << std::endl;
return 0;
}
gdb binFile
:进入gdb环境,其中binFile是一个可执行程序。
l(list)
:显示binFile
的源代码,接着上次的位置往下列,每次10行。
l num
或list num
:其中num是行号,将源代码的第num行在中间位置显示。
r(run)
:运行程序。
b(break) 行号
:在某一行设置断点。
info b(info break 或者 i b)
:查看断点信息。
d(delete) Num
:删除一个断点,其中Num是断点编号。
注意:如果在调试过程中退出,那么再次进入调试环境,上一次的调试信息会丢失,即之前设置的断点都没了。
此时设置完断点之后我们再次运行程序(使用 r
命令 ),它就会直接运行至第一个断点处并且停止运行。
-
n(next)
:逐过程,单条执行,当有函数调用时,不会进入函数内部。
我们接着上面的代码走。
-
s(step)
:逐语句,进入函数调用。
-
p 变量
:打印变量的值。
注意 :通过p
来打印变量的值,不会根据我们调试的进行而实时变化。 -
display 变量名
:跟踪查看一个变量,每次停下来都显示它的值,类似于Visual Studio中的监视窗口。
可以随着代码的运行而显示变量的变化。
-
undisplay num
:取消对先前设置的那些变量的追踪,其中num是先前设置的跟踪变量所对应的编号。
此时有一个问题,假如我进入循环之后查看了几轮发现代码没有问题,想快速结束这个循环怎么办?
-
until x
:跳至x行,可以让我们快速的运行代码块。
-
finish
:执行完当前函数返回,然后停下来等待命令。
注意 :finish
指令可以快速的帮我们查看问题是不是出在当前函数中。 -
c(continue)
:从当前断点直接运行到下一个断点处。
-
disable Num
:禁用断点,其中Num
是断点编号。禁用完1,2两个断点之后,此时再次运行,程序直接跳转到了第三个断点处
-
enable Num
:启用断点,其中Num
是断点编号。
🍮4.3 常用 GDB 指令表
命令 | 缩写 | 功能描述 | 示例 |
---|---|---|---|
运行与调试控制 | |||
run |
r |
启动程序并运行 | run arg1 arg2 |
start |
无 | 从程序入口运行并暂停在main |
start |
continue |
c |
恢复程序运行直到下一个断点 | continue |
step |
s |
单步执行(进入函数调用) | step |
next |
n |
单步执行(跳过函数调用) | next |
finish |
无 | 运行到当前函数返回 | finish |
until |
无 | 运行到指定行或跳出循环 | until 45 |
quit |
q |
退出 GDB | quit |
断点操作 | |||
break |
b |
设置断点(支持行号、函数、文件等) | break main break 25 |
tbreak |
无 | 设置临时断点,仅触发一次 | tbreak my_function |
info breakpoints |
i b |
查看所有断点信息 | info breakpoints |
delete |
d |
删除指定断点 | delete 1 |
clear |
无 | 删除某位置的断点(行号或函数) | clear 30 |
enable |
无 | 启用指定断点 | enable 2 |
disable |
无 | 禁用指定断点 | disable 2 |
condition |
无 | 为断点设置条件 | condition 1 x > 5 |
变量与表达式 | |||
print |
p |
打印变量值或表达式结果 | print x print x + y |
display |
无 | 每次暂停时自动显示指定变量 | display var |
undisplay |
无 | 停止显示指定编号的变量 | undisplay 1 |
set var |
无 | 修改变量值 | set var x = 10 |
whatis |
无 | 显示变量类型 | whatis var |
调用栈与线程 | |||
backtrace |
bt |
显示调用栈 | backtrace |
frame |
f |
切换到指定栈帧 | frame 2 |
info threads |
无 | 显示所有线程 | info threads |
thread |
无 | 切换到指定线程 | thread 3 |
内存操作 | |||
x/<n><fmt> |
无 | 查看内存内容(支持格式化输出) | x/4xw 0x123456 |
x/s |
无 | 查看内存地址的字符串 | x/s 0x7fff1234 |
info registers |
无 | 查看所有寄存器内容 | info registers |
set |
无 | 修改内存地址内容 | set *(int *)0x123456 = 42 |
源码查看 | |||
list |
l |
查看当前代码上下文 | list |
list <line> |
l |
查看指定行代码 | list 50 |
list <function> |
l |
查看指定函数的源码 | list my_function |
文件与进程 | |||
file |
无 | 加载可执行文件 | file ./a.out |
attach |
无 | 附加到运行中的进程 | attach 1234 |
detach |
无 | 分离调试器和程序 | detach |
🍮4.4 指令总结与使用场景
程序控制:
- 常用的运行控制指令包括
run
、continue
、step
和next
。 - 当程序异常终止时,可以结合
backtrace
查看调用栈,分析错误。
断点管理:
- 通过
break
设置断点,info breakpoints
查看断点状态。 - 如果调试某段特定代码,可使用
condition
设置条件断点。
变量与内存调试:
- 使用
print
查看变量值,set var
修改变量,快速验证修复效果。 - 若需深入分析内存,结合
x
命令和格式化选项查看内存内容。
多线程调试:
- 对多线程程序,先用
info threads
查看线程列表,再切换到目标线程进行分析。
高级场景:
- 使用
attach
调试运行中的程序或core
文件分析崩溃问题。
结语
Linux 工具链的丰富性和灵活性,为开发者提供了从项目开发到部署的全套解决方案。本篇文章介绍了 Linux 中的核心工具,从软件管理到编译、调试以及自动化构建,希望为您在开发工作中提供实用的参考。在掌握这些工具之后,您将能以更高效的方式处理日常开发任务,同时通过进一步挖掘这些工具的高级功能,解锁更多的 Linux 技能潜力。如果您遇到问题或有新的需求,欢迎继续探索并学习更多 Linux 相关知识,迈向更高的技术水平!
今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连 支持一下,17的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是17前进的动力!