一、软件包管理器:yum/apt
什么是软件包管理器?
这是一个运行在你服务器上的工具,它负责帮你去服务器上查找、下载、安装、卸载软件,并自动解决依赖问题 。就类似于手机上的**"App Store"。**
常见的包管理器:
- CentOS/RedHat/Fedora 生态 :主要使用 yum 。
- Ubuntu/Debian 生态 :主要使用 apt 。
1.1 核心操作三板斧
在日常开发中,我们最常用的就是查找 、安装 和卸载 。这里以 lrzsz 工具(一个用于在 Windows 和 Linux 间通过终端传输文件的工具)为例演示。
注意 :安装和卸载操作涉及系统目录的修改,通常需要
root权限或使用sudo提权 。且yum在同一时刻只能允许一个安装进程运行 。
查找软件包
当我们不知道软件的确切名称时,可以进行搜索。
CentOS (yum):
bash
# 列出所有包含 lrzsz 关键字的包
[she@VM-0-15-centos test]$ yum list | grep lrzsz
其中 yum list 的作用是罗列出可供下载的全部软件。

说明一下:
1)软件包名称:主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构。
2)"x86_64"后缀表示64位系统的安装包,"i686"后缀表示32位系统安装包,选择包时要和系统匹配。
3)"el7"表示操作系统发行版的版本,"el7"表示的是"centos7/redhat7","el6"表示"centos6/redhat6"。
4)最后一列表示的是"软件源"的名称,类似于"小米应用商店","华为应用商店"这样的概念。
Ubuntu (apt):
apt search lrzsz
安装软件
找到名字后,一键安装。-y 选项表示自动确认,不需要你在安装过程中手动按 "y"。
CentOS:
bash
[she@VM-0-15-centos test]$ sudo yum install -y lrzsz
提示 "Complete!" 即表示安装成功 。
注意事项:
1)安装软件时由于需要向系统目录中写入内容,一般需要sudo或者切换到root账户下才能完成。
2)yum安装软件只能一个装完了再装另一个,正在使用yum安装一个软件的过程中,如果再尝试用yum安装另外一个软件,yum会报错。
Ubuntu:
bash
she@VM-24-16-ubuntu:~/test$ sudo apt install -y lrzsz
卸载软件
CentOS:
bash
[she@VM-0-15-centos test]$ sudo yum remove -y lrzsz
Ubuntu:
bash
she@VM-24-16-ubuntu:~/test$ sudo apt remove -y lrzsz
1.2 软件从哪下的
我们知道 yum/apt 是从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。
而这个指定的包服务器链接就处于特定的配置文件中。

配置文件
CentOS: 配置文件位于 /etc/yum.repos.d/ 目录下 。CentOS-Base.repo是官方的标准源配置。
Ubuntu: 配置文件位于 /etc/apt/sources.list 。
默认的软件源服务器通常在国外。由于物理距离和网络原因,下载速度可能非常慢。为了加速,国内的高校和企业(如阿里云、清华大学、中科大等)同步了官方的软件库,提供了国内镜像源 。
例如:
- 阿里云镜像站 :https://developer.aliyun.com/mirror/
- 清华大学开源镜像站 :https://mirrors.tuna.tsinghua.edu.cn/
配置国内源的本质,就是修改上述的配置文件,将下载链接指向国内的服务器,从而极大地提升下载速度。
扩展话题:
有时候你用
yum install发现找不到某些软件(比如sl小火车动画,或者较新版本的开发工具)。这是因为官方的基础源只包含最稳定、最通用的软件。这时候我们需要安装 EPEL,它是一个提供了丰富额外软件包的仓库。
安装 EPEL 源:
bash[she@VM-0-15-centos test]$ sudo yum install -y epel-release安装完成后,你的
/etc/yum.repos.d/下会多出一个epel.repo文件,再次搜索就能找到更多好玩的软件了 。
二、Linux编辑器 - vim
与 Notepad 或 VS Code 不同,Vim 是一个 多模式编辑器。
在绝大多数时间里,我们是在阅读和修改代码,而不是在输入新代码。因此,Vim 将键盘的大部分按键都赋予了编辑功能,让你手不离键盘热区就能完成极其复杂的操作。
2.1 核心模式
我们这里主要介绍vim最常用的三种模式:命令模式、插入模式、底行模式。
正常模式:
- 进入 Vim 的默认模式。
- 作用:移动光标、删除文本、复制粘贴。在这个模式下,你按下的键是命令 ,而不是字符。
- 按
Esc键,永远可以回到这个模式。
插入模式:
作用:像普通编辑器一样输入文字。
进入方式:
i:在光标当前位置前插入。
a:在光标当前位置后插入。
o:在当前行下方新开一行插入。
末行模式:
作用:保存、退出、搜索、替换、设置行号。
进入方式 :在正常模式下按
shift + :(即输入冒号:)。
模式之间的切换如下图所示

vim命令模式各命令汇总
【移动光标】
-
按「k」:光标上移。
-
按「j」:光标下移。
-
按「h」:光标左移。
-
按「l」:光标右移。
-
按「$」:移动到光标所在行的行尾。
-
按「^」:移动到光标所在行的行首。
-
按「gg」:移动到文本开始。
-
按「Shift+g」:移动到文本末尾。
-
按「n+Shift+g」:移动到第n行行首。
-
按「n+Enter」:当前光标向下移动n行。
-
按「w」:光标从左到右,从上到下的跳到下一个字的开头。
-
按「e」:光标从左到右,从上到下的跳到下一个字的结尾。
-
按「b」:光标从右到左,从下到上的跳到上一个字的开头
【删除】
-
按「x」:删除光标所在位置的字符。
-
按「nx」:删除光标所在位置开始往后的n个字符。
-
按「X」:删除光标所在位置的前一个字符。
-
按「nX」:删除光标所在位置的前n个字符。
-
按「dd」:删除光标所在行。
-
按「ndd」:删除光标所在行开始往下的n行。
【复制粘贴】
-
按「yy」:复制光标所在行到缓冲区。
-
按「nyy」:复制光标所在行开始往下的n行到缓冲区。
-
按「yw」:将光标所在位置开始到字尾的字符复制到缓冲区。
-
按「nyw」:将光标所在位置开始往后的n个字复制到缓冲区。
-
按「p」:将已复制的内容在光标的下一行粘贴上。
-
按「np」:将已复制的内容在光标的下一行粘贴n次。
【剪切】
-
按「dd」:剪切光标所在行。
-
按「ndd」:剪切光标所在行开始往下的n行。
-
按「p」:将已剪切的内容在光标的下一行粘贴上。
-
按「np」:将已剪切的内容在光标的下一行粘贴n次。
【撤销】
-
按「u」:撤销。
-
按「Ctrl+r」:恢复刚刚的撤销。
【大小写切换】
-
按「~」:完成光标所在位置字符的大小写切换。
-
按「n~」:完成光标所在位置开始往后的n个字符的大小写切换。
【替换】
-
按「r」:替换光标所在位置的字符。
-
按「R」:替换光标所到位置的字符,直到按下「Esc」键为止。
【更改】
-
按「cw」:将光标所在位置开始到字尾的字符删除,并进入插入模式。
-
按「cnw」:将光标所在位置开始往后的n个字删除,并进入插入模式。
【翻页】
-
按「Ctrl+b」:上翻一页。
-
按「Ctrl+f」:下翻一页。
-
按「Ctrl+u」:上翻半页。
-
按「Ctrl+d」:下翻半页。
vim底行模式各命令汇总
在使用底行模式之前,记住先按「Esc」键确定你已经处于命令模式,再按「:」即可进入底行模式。
【行号设置】
1.「set nu」:显示行号。
2.「set nonu」:取消行号。
【保存退出】
1.「w」:保存文件。
2.「q」:退出vim,如果无法离开vim,可在「q」后面跟一个「!」表示强制退出。
3.「wq」:保存退出。
【分屏指令】
1.「vs 文件名」:实现多文件的编辑。
2.「Ctrl+w+w」:光标在多屏幕下进行切换。
【执行指令】
1.「!+指令」:在不退出vim的情况下,可以在指令前面加上「!」就可以执行Linux的指令,例如查看目录、编译当前代码等。
2.2 Vim 配置
原生的 Vim 界面非常简陋(没有行号,语法不高亮)。为了让它更好用,我们需要配置它。
Vim 的配置原理是读取一个配置文件。
-
全局配置 :
/etc/vimrc(影响所有用户)。 -
用户配置 :
~/.vimrc(仅影响当前用户)。如果该文件不存在,可以手动创建 。
一个简单的 .vimrc 配置示例: 你可以直接在终端输入 vim ~/.vimrc,然后写入以下内容:
" 开启语法高亮
syntax on " [cite: 490]
" 显示行号
set nu " [cite: 491]
" 设置缩进为 4 个空格
set shiftwidth=4 " [cite: 492]
set tabstop=4
set autoindent " 自动缩进
vim的配置比较复杂,建议不要自己一个个去配置。比较简单的方法是直接执行以下指令:
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh
然后按照提示输入root密码后,等待安装配置,最后手动执行source ~/.bashrc即可。
三、Linux编译器 - gcc/g++
gcc和g++分别是GNU的C和C++的编译器,gcc和g++在执行编译的时候一般有以下四个步骤:
预处理: 头文件展开、去注释、宏替换、条件编译。
编译: C代码翻译成汇编语言。
汇编: 汇编代码转为二进制目标代码。
链接: 将汇编过程产生的二进制代码进行链接。
3.1 预处理
我们在shell运行 gcc -E test.c -o test.i

- 预处理功能主要包括头文件展开、去注释、宏替换、条件编译等。
- 预处理指令是以#开头的代码行。
- -E选项的作用是让gcc/g++在预处理结束后停止编译过程。
- -o选项是指目标文件,"xxx.i"文件为已经过预处理的原始程序。
3.2 编译
继续运行 gcc -S test.i -o test.s

- 在这个阶段中,gcc/g++首先检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,将代码翻译成汇编语言。
- 用户可以使用-S选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
- -o选项是指目标文件,"xxx.s"文件为已经过翻译的原始程序。
3.3 汇编
继续运行 gcc -c test.s -o test.o

- 汇编阶段是把编译阶段生成的"xxx.s"文件转成目标文件。
- 使用-c选项就可以得到汇编代码转化为"xxx.o"的二进制目标代码了。
3.4 链接
继续运行 gcc test.o -o test

- 在成功完成以上步骤之后,就进入了链接阶段。
- 链接的主要任务就是将生成的各个"xxx.o"文件进行链接,生成可执行文件。
- gcc/g++不带-E、-S、-c选项时,就默认生成预处理、编译、汇编、链接全过程后的文件。
- 若不用-o选项指定生成文件的文件名,则默认生成的可执行文件名为a.out。
注意: 链接后生成的也是二进制文件。
动静态库:
函数库一般分为静态库和动态库两种:
静态库是指编译链接时,把库文件的代码全部加入到可执行文件当中,因此生成的文件比较大,但在运行时也就不再需要库文件了,静态库一般以.a为后缀。
动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件当中,而是在程序运行时由链接文件加载库,这样可以节省系统的开销,动态库一般以.so为后缀。
那么在链接阶段,有一个核心概念:我们的程序依赖的库(如 libc)是怎么"塞"进来的?
静态链接:
- 原理 :在编译时,将库文件的代码全部拷贝到可执行文件中 。
- 优点:程序独立,不依赖运行环境(移植方便)。
- 缺点 :文件体积大,浪费磁盘和内存(如果有100个程序都用
printf,内存里就有100份printf的代码副本) 。 - 后缀 :Linux 下通常为
.a。
动态链接------ GCC 默认行为
-
原理 :编译时不拷贝代码,只记录需要用到的库的地址/链接。程序运行时,由操作系统动态加载库文件 。
-
优点:节省资源,库文件更新时无需重新编译程序 。
-
缺点:依赖运行环境,如果缺少库文件,程序无法运行。
-
后缀 :Linux 下通常为
.so。
gcc和g++默认生成的二进制程序是动态链接的,我们可以使用 file 指令进行查看。

其次,我们还可以使用ldd指令查看动态链接的可执行文件所依赖的库。

图中的/lib64/libc.so.6就是当前云服务器当中的C标准库。
常用选项
-g:生成调试信息(GDB 调试必选) 。-O0 / -O1 / -O2 / -O3:优化级别,-O3优化最高 。-static:强制采用静态链接 。
四、自动化构建:Make & Makefile
Makefile:是一个文本文件,定义了一系列的规则,告诉系统哪些文件需要先编译,哪些需要后编译,以及如何编译 。
make:是一个命令工具,它解释 Makefile 中的指令,实现自动化构建。
一旦写好 Makefile,只需要输入一个 make 命令,整个工程就会自动编译,极大提高开发效率 。
依赖关系与依赖方法
Makefile 的编写遵循一个最基本的格式:
bash
目标文件: 依赖文件列表
[Tab] 依赖方法 (必须以 Tab 键开头)
列如
bash
myproc: myproc.c
gcc -o myproc myproc.c
依赖关系 :myproc 依赖于 myproc.c 。也就是说是myproc 目标文件,myproc.c是依赖文件。
依赖方法 :执行 gcc -o myproc myproc.c 来生成它 。
第一次 make 后,如果源文件没有修改,再次 make 会提示 "make: 'myproc' is up to date.",而不会重新编译。原因是因为时间戳对比.
Linux 系统中,文件有三个时间属性(可以通过 stat filename命令查看):
-
Access:最近访问时间。
-
Modify:文件内容最近修改的时间。
-
Change:文件属性最近修改的时间。
Make 的逻辑很简单:如果目标文件的 Modify 时间 早于 依赖文件的 Modify 时间,说明依赖文件被修改过,需要重新编译;否则不需要。
Makefile文件的简写方式:
- $@:表示依赖关系中的目标文件(冒号左侧)。
- $^:表示依赖关系中的依赖文件列表(冒号右侧全部)。
- $<:表示依赖关系中的第一个依赖文件(冒号右侧第一个)。
项目清理
我们在构建项目时,常需要清除旧的生成文件。通常定义一个 clean 目标。 为了防止当前目录下有名为 clean 的文件干扰,我们使用 .PHONY 将其声明为 伪目标,表示它总是被执行,不检查时间戳 。
列如
bash
test_thread:test_thread.cc
g++ -o $@ $^ -lpthread
.PHONY:clean
clean:
rm -f test_thread
五、版本控制器:Git
Git是个工具,需要主动去安装,结合之前的内容,
bash
[she@VM-0-15-centos test]$ sudo yum install git # CentOS
# 或 sudo apt install git
第一次配置
安装后,你需要告诉 Git 你是谁
bash
[she@VM-0-15-centos test]$ git config --global user.name "Your Name"
[she@VM-0-15-centos test]$ git config --global user.email "you@example.com"
这种配置会记录在每一次提交中,因为修改了config文件。
获取项目
通常我们在 Github/Gitee 上创建一个仓库,然后将其克隆到本地:
bash
[she@VM-0-15-centos test]$ git clone [仓库链接]
5.1 核心操作"三板斧"
第一板斧:git add (暂存)
当你修改了代码),你需要告诉 Git 哪些文件需要被管理。
bash
[she@VM-0-15-centos test]$ git add process.c # 添加指定文件
# 或者
[she@VM-0-15-centos test]$ git add . # 添加当前目录下所有变动
第二板斧:git commit (提交)
将暂存区的内容真正提交到本地仓库。要注意必须填写提交日志!
bash
[she@VM-0-15-centos test]$ git commit -m "写好了第一个程序"
这一步完成后,你的代码就已经被永久记录在本地的版本历史中了。
第三板斧:git push (推送)
将本地仓库的记录同步到远端服务器,实现异地备份和多人协作。
bash
[she@VM-0-15-centos test]$ git push
此时你需要输入 Github 的账号密码。
在编译 C/C++ 项目时,会生成大量的中间文件(如 .o)和可执行文件(如 myproc)。这些文件不需要也不应该被提交到代码仓库。
我们可以创建一个名为 .gitignore 的文件,在里面列出要忽略的文件模式:
列如
bash
# 忽略所有的 .o 文件
*.o
# 忽略可执行文件
myproc
这样,git 的时候就不会提交这些没必要的文件了 。
六、Linux调试器 - gdb
6.1 gdb使用须知
程序发布方式:
1、debug版本:程序本身会被加入更多的调试信息,以便于进行调试。
2、release版本:不会添加任何调试信息,是不可调试的。
在Linux当中gcc/g++默认生成的可执行程序是release版本的,是不可被调试的。如果想生成debug版本,就需要在使用gcc/g++生成可执行程序时加上-g选项。
对同一份源代码分别生成其release版本和debug版本的可执行程序,debug版本发布的可执行程序的大小比release版本发布的可执行程序的大小要大一点,其原因就是以debug版本发布的可执行程序当中包含了更多的调试信息。
可以通过 file 命令查看是否就有调试信息,输出中会带有 with debug_info 字段。
gdb命令汇总
- 开始: gdb binFile
- 退出: ctrl + d 或 quit 调试命令
| 命令 | 作用 | 样例 |
|---|---|---|
| list/l | 显示源代码,从上次位置开始,每次列出 10 行 | list/l 10 |
| list/l 函数名 | 列出指定函数的源代码 | list/l main |
| list/l 文件名:行号 | 列出指定文件的源代码 | list/l mycmd.c:10 |
| r/run | 从程序开始连续执行 | run |
| n/next | 单步执行,不进入函数内部(逐过程),对应 F10 | next |
| s/step | 单步执行,进入函数内部(逐语句),对应 F11 | step |
| break/b [文件名:] 行号 | 在指定行号设置断点 | break 10break test.c:10 |
| break/b 函数名 | 在函数开头设置断点 | break main |
| info break/b | 查看当前所有断点的信息 | info break |
| finish | 执行到当前函数返回,然后停止 | finish |
| print/p 表达式 | 打印表达式的值 | print start+end |
| p 变量 | 打印指定变量的值 | p x |
| set var 变量 = 值 | 修改变量的值 | set var i=10 |
| continue/c | 从当前位置开始连续执行程序 | continue |
| delete/d breakpoints | 删除所有断点 | delete breakpoints |
| delete/d breakpoints n | 删除序号为 n 的断点 | delete breakpoints 1 |
| disable breakpoints | 禁用所有断点 | disable breakpoints |
| enable breakpoints | 启用所有断点 | enable breakpoints |
| info/i breakpoints | 查看当前设置的断点列表 | info breakpoints |
| display 变量名 | 跟踪显示指定变量的值(每次停止时自动打印) | display x |
| undisplay 编号 | 取消对指定编号的变量的跟踪显示 | undisplay 1 |
| until X 行号 | 执行到指定行号 | until 20 |
| backtrace/bt | 查看当前执行栈的各级函数调用及参数 | backtrace |
| info/i locals | 查看当前栈帧的局部变量值 | info locals |
| quit | 退出 GDB 调试器 | quit |