目录
[1. 软件包管理器 yum](#1. 软件包管理器 yum)
[1.1 安装软件的方式](#1.1 安装软件的方式)
[1.2 yum 指令](#1.2 yum 指令)
[2. vim(编辑器)](#2. vim(编辑器))
[2.1 vim 的简单操作](#2.1 vim 的简单操作)
[2.1.1 方向键(HJKL)](#2.1.1 方向键(HJKL))
[2.1.2 退出 vim](#2.1.2 退出 vim)
[2.2 vim 文本批量化操作(命令模式)](#2.2 vim 文本批量化操作(命令模式))
[2.2.1 复制.粘贴.删除.剪贴.撤销](#2.2.1 复制.粘贴.删除.剪贴.撤销)
[2.2.2 光标跳转](#2.2.2 光标跳转)
[2.2.3 vim其它操作](#2.2.3 vim其它操作)
[2.3 配置 vim](#2.3 配置 vim)
[3. gcc 和 g++](#3. gcc 和 g++)
[3.1 程序的翻译过程](#3.1 程序的翻译过程)
[3.1.1 预处理](#3.1.1 预处理)
[3.2.2 编译(生成汇编)](#3.2.2 编译(生成汇编))
[3.2.3 汇编(简单了解)](#3.2.3 汇编(简单了解))
[3.2.4 链接(下篇详解)](#3.2.4 链接(下篇详解))
[4. gdb(调试器)](#4. gdb(调试器))
[4.1 list/l(显示源代码)](#4.1 list/l(显示源代码))
[4.2 断点的相关操作](#4.2 断点的相关操作)
[4.3 调试的相关操作](#4.3 调试的相关操作)
[4.4 gdb总结](#4.4 gdb总结)
1. 软件包管理器 yum
Windows 下我们是如何装软件的?
我们可以百度上搜索,然后进入官网下载安装包,之后打开安装包进行安装,
我们顶多要做的就是勾勾选选,设置一下安装到哪个盘,总体来说还是非常容易的。
那在 Linux 下安装软件,会像 Windows 下这么方便吗?答案是不会!
在 Linux 下安装软件,最通常的方式是去下载程序的源代码并进行编译,从而得到可执行程序。Linux 没有图形化界面,正是因为太麻烦,所以有些人就把一些常用的软件提前编译好并做成软件包,放到服务器上。
你只需要通过包管理器,就可以轻而易举地获取到这个编译好的软件包,直接安装。
1.1 安装软件的方式
Centos 7中安装软件分为三种方式: ①源码安装 ② rpm 包安装 ③yum 安装
① 源码安装:
源码安装就相当于,我把项目源代码给用户,让用户自己去编译去......
② rpm 包安装:
你可以理解为 Linux 下的安装包,只是下载好 rpm 包后想安装还需要用 rpm 命令,
比较麻烦,而且 rpm 包安装不会帮你解决依赖关系(有些软件是需要依赖的)。
换句话说就是 ------ 你下一个软件,就真的只有一个软件,依赖什么软件完全需要你自己去解决。
而我们比如下载QQ一键就可以安装,那是因为腾讯已经帮你把需要的东西打包好了,
也就不需要你去解决依赖关系了,但是 Linux 下没有人直接做这样得事情。
③yum 安装
如果只有源码和 rpm 包这两种安装方式,就连开发者用起来都头大,那更别说用户了。
于是 Linux 就推出了一个简单的集成化安装方案 ------ yum 安装。
yum 安装最大的好处显而易见,不用编译源码,且不用解决软件的依赖关系。
Linux 软件包管理器 yum
在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软件包, 直接进行安装. 软件包和软件包管理器, 就好比 "App" 和 "应用商店" 这样的关系. yum(Yellow dog Updater, Modified)是Linux下非常常用的一种包管理器. 主要应用在Fedora, RedHat, Centos等发行版上.
1.2 yum 指令
yum install 软件名(下载软件)
我们之前的文章也接触过yum了,再下载一个小工具回顾一下:
有一个叫 sl 的小工具,这个工具是可以在命令行跑 "火车头" 的软件。
在大家的系统中默认情况下是没有这个软件的,现在正好可以来试试用 yum 安装:
这篇文章就先切换到root用户,输入yum install sl(有询问就输入y确定)
也可以输入yum install -y vim(y表示确认,-y就让你不要问了,下载和卸载都一样)

显示 Complete! 即安装成功,此时我们输入 sl 看看效果如何:

由此可见,用 yum 安装软件非常简单,下面我们来正式讲解一下 yum 。
我们要安装别人的软件,需要做的准备工作:
① 需要别人先把代码给我编译成可执行程序。
② 需要有人将编好的软件,放在用户能下载的地方。
在 Linux 也是一样的,以手机应用市场 APP 为例:
你手机上的 APP 是属于客户端还是服务器?
手机上的 APP 实际上是客户端,而不是服务器。云服务器相信大家并不陌生,我们所用的 XShell 其实就是一个客户端,我们登陆的是远端的服务器。
yum 就类似于手机上的应用市场APP。
既然要安装软件,我们得知道软件的名字是什么,如果我们不知道软件叫什么那么自然也没法装。
这就是为什么手机应用市场有应用推荐这个功能,按类别去给你推荐软件供你下载。
yum list(显示可以下载的软件)
Linux 下我们可以通过 yum list 指令去执行类似于手机应用市场的 "软件推荐" 功能:
输入yum list 就会把你所有可以下载的软件列出来(这是非常多的):

升级后能下载的还会更多,如果下载过的继续下载:(比如刚才下载的sl小火车)

会提示你已经下载过了,并且是最新版本,然后Nothing to do
yum remove 软件名(卸载软件)
yum 既然能安装软件,自然也是能卸载软件的。
忍痛把我们刚才下载的 sl 小火车删掉:

2. vim(编辑器)
vim 是什么?
它是一个编辑器!只能用来写代码,编译 vim 也做不到,有其他工具帮我们做。
既然只能用来写代码,那我们为什么不用 nano 记事本呢,不都一样吗?
当然不一样,vim 功能强大,是一个多模式的编辑器。因为过于强大,学习成本固然较高。
我们之去学习它的一些常用的功能,一些边边角角的功能以后可以慢慢学习。
你可以输入 vim 确认一下你有没有安装过 vim,若显示 bash: vim: command not found ,
那就说明还没有安装 vim,我们用刚刚学习的 yum 安装一下即可:yum install -y vim
2.1 vim 的简单操作
为什么要学 vim?vim 是一个用来快速的解决问题、迅速查阅的一个非常好的工具。
有时候,需要我们在生产环境下,需要你快速的定位问题,甚至需要你快速的修改代码!
vim 实际上是非常职业化的工具,你不懂也不影响开发,你懂,就是个如虎添翼的东西。
为了方便演示:在/home/rtx2新建一个linux_5目录,进入并建立一个test.c文件:

随后输入 vim test.c,就可以用 vim 编辑器打开该文件了,
进入之后,此时你会发现是输入不了任何东西的,似乎没有反应:

vim有很多种模式,目前掌握这3种即可:默认模式、底行模式和插入模式

第一次打开 vim 时的命令模式为 "默认模式" 此时是输入不了任何东西的
不乏一些新手首次使用时,在不看任何 "攻略" 的情况下,随便按按键,可以 "侥幸" 打出字。
那是因为按到了 i 这个按键,没按到 i 的按一下 i,
**注意事项:**不仅仅 i 可以进入插入模式,还有 a 和 o ,可以自己去试试。
按 a 进入插入模式后初始光标位置为第二个字符,而 o 进入插入模式后初始光标在第二行。
进入了 "插入模式",左下角会显示 :

此时我们就可以正常打字了,我们来写一个经典的 hello 程序测试一下效果:

(你输入的没有颜色和自动补齐等功能是因为你的vim还没有进行配置,稍后再讲如何配置)
2.1.1 方向键(HJKL)
我们是可以通过键盘上的方向键去进行光标移动的。
但是我们是不太推荐用上下左右键去进行光标移动的,我们建议用 "HJKL"
为什么建议使用 HJKL而不使用我们一直习惯的**↑ ↓ ← →** 呢?
因为我们后面会学一些组合命令,比如批量化注释,它只能支持用 HJKL。
至于为什么 vim 它的上下左右是这几个按键呢?

老式键盘是没有上下左右键的,以前就是那 HJKL 充当 上下左右键的:
这样的上下左右移动方式好奇怪啊,不是所见即所得的 ↑ ↓ ← → ,但我们可以这么记:


2.1.2 退出 vim
如果想退出,我们要输入键盘上的 Esc 按键 ,(任何模式想回到命令模式,无脑 Esc 即可)
此时是命令模式,再按冒号就可以回到底行模式,然后输入wq(w是保存,q是退出,可以分别输入,(输入q感叹号就是不存盘强制退出vim))

回车退出去之后我们来 cat 一下看看我们刚刚写的内容:

2.2 vim 文本批量化操作(命令模式)
2.2.1 复制.粘贴.删除.剪贴.撤销
yy(复制)和p(粘贴)
如果我想粘贴 100 次,我难道要按100次 p 吗?
当然不用,我们可以使用批量化粘贴 的功能:输入 100p
(这些数字都需按字母上面的数字,而是不键盘右边的)
对应的,还有批量化复制 的功能,

此时我们可以Esc然后输入 :q! 不保存退出
x 删除当前光标位置字符
n r(删除当前光标位置开始的全部后n个字符)
dd(剪贴光标指定行内容)
n dd (剪贴光标为参考系对应的下面全部 n 行内容(包括当前行) )
值得一提的是,dd 也可以当删除去使用,你只要不 p 他就等于是删除的效果了。

可以这样标序号去试试,这里就不演示了。
u(撤销) 和 Ctrl r(收回撤销)
我删着删着后悔了怎么办?u(撤销)
诶,这个时候我又后悔了,我想收回刚才的 u 撤销,怎么办? Ctrl r(收回撤销)
2.2.2 光标跳转
gg(光标快速定位到文本的最开始)
shift g (光标快速定位到文本末尾)
n shift g(将光标快速定位到文本的任意 (n) 行)
2 shift g:
如果想让光标跳到当前所在的文本行开头/结尾呢?

shift ^(光标快速定位到文本行的开始)
shift $(光标快速定位到文本行的末尾(我们称 $ 为 "锚点" ))
2.2.3 vim其它操作
vim下的操作是很多的,可以去网上顺便搜,这里演示一些常用的。
w / b(以单词为单位移动(warp 与 back)w是向后移动,b是向前移动)
(突然发现return 0; 都能写错了,不过问题不大,然后下面是输入w的变化:)
shift ~(大小写快速切换)一直按着的变化:
shift r(进入replace模式)
进入 replace 模式后,光标所在处直接输入即可替换,你的所有输入的都会直接替换。
这非常类似于 Windows 中恼人的 Insert 键。(无脑Esc就回到命令模式)
直接进入replace模式然后输入printf:
2.3 配置 vim
默认的 vim 没有配置,没有提示、没有缩进、没有行,这就太不方便了。
vim 的个别配置可以在csdn直接搜,
我们先这里提供一个能够直接输入指令一键配置的方法,让大家先能用起来,
至于具体的 vim 配置学习我们会放到会面去讲解。
某神为了解决小白在配置 vim 时十分繁琐的问题,于是在 gitee 中上传了一份自动配置方案。唯一的缺点是:该配置当前只支持 Centos 7 版本,**这里切换到普通用户,**直接无脑复制下面的命令,shift+insert 粘贴到命令行:
cpp
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh &&bash ./install.sh
(普通用户这里会让你输入root密码,root用户可能会导致安装不成功)
此时就进入了安装阶段(前提是你的 yum 都要搞好),安装完成后,我们再打开 vim 看看:

复制上面的命令然后打开上面写的test.c(或者新建一个)重写一份:

此时语法高亮,自动补齐,缩进什么的都有了,不过它默认缩进两个空格,以前在VS2022都习惯自动缩进四个空格,强迫症可以这样改:在/home/rtx2路径下输入vim .vimrc进入.vimrc文件

按J滑下来:在50到52行,把三个2都改为4,然后按Esc建到命令模式,:wq保存退出
再进入vim写代码就是自动缩进四个空格了:

3. gcc 和 g++
在 Linux 中如何编译 C/C++ ?
gcc 文件名(编译C)
g++ 文件名(编译C++)
此外,如果你输入"g++ test.cpp" 时显示并没有这样的指令,可以切换到root用户安装一下:
cpp
yum install -y gcc-c++
gcc 是不能用来编译 C++ 代码的,它只能用来编译 C 语言的代码,
但是, g++ 是可以用来编译 C 语言的,这个相信大家是可以理解的,因为 C++兼容C语言
3.1 程序的翻译过程
程序(文本)要转换成机器语言(二进制),翻译有以下四个步骤:
- ① 预处理 ② 编译(生成汇编) ③ 汇编 ④ 链接
这个我们以前文章已经讲过了,我们本节主要讲解预处理部分,并且对链接部分进行补充。
对于编译和汇编部分,本节我们只对他们做一个简单的讲解(当然并不是说它们不重要)
我们知道文本要翻译成二进制的原因是计算机只认识二进制,那你有没有想过:
为什么计算机只认识二进制?
其实并不是计算机只认识二进制,而是计算机当中的各种硬件只认识二进制。
在计算机刚被设计的时候都是存储两派信息,常见的比如触发器这样的硬件设备,
实际上只能存储电信号的 "有无" 或者 "正负" 这样的概念,至于为什么选择二进制。
我再做一个补充,其实从计算机发明到现在,历史上也出现过其它进制的计算机。
比如苏联的三进制计算机,只不过二进制计算机更简单,最后成为主流了。
所以,我们的计算机只认识二进制,因为它的各种硬件都是二进制的。
答案:组成计算机的各种组件,只认识二进制。
3.1.1 预处理
**预处理:**a. 宏替换 b. 头文件展开 c. 去注释 d. 条件编译
Linux 的 gcc 是如何进行上面的过程的呢?我们先看预处理的过程。
我们来修改一下 上面的 test.c 源文件,让它有头文件、宏、注释和条件编译:

保存退出,此时我们直接用 gcc 编译一下代码,"gcc 要编译的文件名" 默认生成的可执行程序叫 a.out。如果你不想让生成的可执行程序为叫 a.out,你想指定名称,可以加上 -o 选项:

这样是直接一步到位地获得了可执行程序,可是我们现在想观察预处理,也就是说我们只想让 gcc 完成预处理的操作(这里习惯后缀为.i),我们可以加上 "杠E" 的选项。

给人最明显的感受就是 ------ test.i 明显要比 test.c 大很多,我们cat tset.i看看:

开头可以发现有大量的引入,但是最后代码的注释和宏替换都被换掉了(英文打错问题不大)
(例子里面我不小心忘记了在代码中用到宏,所以自然前后也没有替换,问题也不大)
我们 vim 打开 test.c,冒号进入底行模式后输入 vs test.i,就可以分屏观察:

回车:

Shift gg:

前面都是stdio.h的一些展开,当你编译的时候实际上是把你的 .h 代码全部拷贝到 .c 中的。以前我们编写C语言代码时 #include<stdio.h> 时,其实并不是说 #include 就一定能成功,前提是你平台必须得装了你引入的头文件,不然也没东西在你的源文件中展开。 编译器内部都必须通过一定的方式,知道你所包含的头文件所在的路径。 现在在回头想一想,为什么一个新的语法老的编译器不支持的问题。其根本原因是因为老的编译器配套的头文件和库,压根就没有这一套东西。我们在装 VS 编译器的时所谓的环境安装勾选 C/C++ 后,实际上就是在给你装 C语言 C++ 的头文件和库。
我们再来比对一下它们的代码部分有什么差别:此时,完成了预处理的工作。
我们刚才的条件编译只保留了 release,这说明vim默认预处理完成的是release版本
换言之,这个预处理工作仅仅是为了让程序翻译的更顺畅,帮助我们做了一些文本替换处理操作而已。比如宏替换、去掉给人读的注释、根据条件编译的结果把不要的选项去掉,此时是一份"干净的C语言" 。
预处理总结:预处理功能主要包括宏定义替换、文件包含、条件编译、去注释等。
预处理指令以 # 号开头的代码行。
实例:gcc -E test.c -o test.i
选项:"-E" 该选项的作用是让 gcc 在预处理结束过后停止编译过程。
选项:"-o" 是指目标文件, "i" 文件为已经过预处理的C初始程序。
3.2.2 编译(生成汇编)
编译的核心工作就是将C语言翻译成汇编语言!
如果看不懂也没有关系,你只要知道 ------ 这一步会让你的C语言代码大变样。
这次我们从 test.i 开始走,当然也可以是 test.c,那会重新走一遍预处理的过程然后再编译。
退出上面,输入gcc -S test.i -o test.s
(和前面.i 类似,汇编语言的后缀一般都叫 .s,所以我们这里取名为 .s,我们前面章节也说过 Linux 的类型和文件后缀没有关系,这里你用 .dauhaud都没有人拦你,只是叫 .s 更符合常理)
输入完上面命令后就形成了 test.s 的文件:

cat test.s一下逝逝:

这是 x86 环境下的汇编指令,其中有一些汇编的助记符,即使看不明白也没有关系。
但是你可以发现代码的数量 从刚才 test.i 的八百多行,变成了现在短短的 几十行。
3.2.3 汇编(简单了解)
该过程是将汇编语言翻译翻译成二进制文件。
准确来说应该是 "可重定位二进制文件",它一般以 .o 结尾,VS 下是 .obj 结尾的。
这里的 "重定位" 和我们前面说的 "重定向" 是完全没有任何关系的,就像雷锋和雷峰塔、Java 和 Javascript 一样完全没有任何关系。
输入gcc -c test.s -o test.o

cat test.o一下再逝逝:

此时就已经是二进制了,打开后会是很大的一坨乱码。
我们可以用一些二进制查看工具去查看, od test.o:

虽然现在代码已经是二进制的了,但是仍然是不能运行的:
其原因也很简单,因为这里面有些符号目前还没有和系统关联起来。

我们一开始一步到位的mytest可以运行,还差最后一步:链接。
3.2.4 链接(下篇详解)
链接相关我们放到下篇讲讲,这里这就输入:
gcc test.o -o mytest2

当然了,直接到程序的翻译过程:gcc test.c -o mytest2
一步就可以到位了,我们之前是为了研究一步步的过程,所以又是 -E 又是 -S 又是 -c 的。
我们先来回故前三个翻译过程,按顺序分别为预处理、编译和汇编。
$ gcc -E test.c -o test.i # 预处理
$ gcc -S test.i -o test.s # 编译
$ gcc -e test.s -o test.o # 汇编
这里有个记忆方法:预处理 (E) → 编译 (S)→ 汇编 (c) ,三个过程就是 ESc。
如果你记不得,可以看看你键盘的左上角就行了(当然前提你要记住程序翻译过程的顺序)。另外它们形成的临时文件为 test.i、test.s、test.o,也同样有个记忆的方法:iso
(国际标准化组织:ISO)
当然,iso 也是镜像文件的后缀,如果你比较熟悉也可以拿这个记。
ISO (Isolation)文件一般以iso为扩展名,是复制光盘上全部信息而形成的镜像文件
4. gdb(调试器)
调试是我们在写程序过程中非常重要的一环,可能大部分时间都是在调试,之前在Windows下的VS2022,只需要按一下F11等快捷键或者点一下命令窗口的选项就可以进行调试,同样的,在Linux下也是可以调试代码的,用到的调试器叫做gdb。
(gdb有很多功能也很复杂,这里只需要懂一些简单的调试就行了)
既然要调试,我们就必须要有个代码,我们在linux_5创建一个test_gdb.c,
在写一个数字累加的代码:(不支持这个for循环可以在gcc最后加上-std=c99)


结果是5050,没有问题。假设我们代码出现了一些问题需要我们调试,我们就可以使用 gdb。
在你当前的代码目录下直接执行 gcb + 形成的可执行程序:这里gdb test_gdb
此时就进入了 gdb 的调试命令行中:(输入quit退出)

但gcb 读取程序时出现了 "没有调试符号被发现" 的警告
我们的 gdb 中有一条命令叫做 list(显示源代码简写成 l),但是我们输入后出现以下提示:

因为默认形成的可执行程序是release版本的,无法调试。
大家都知道,C语言的发布方式有两种,一种是 debug 一种是 release。
我们在 VS 里面可以直接调的原因是,VS2022 的默认集成环境是 debug。
而在我们的 Linux 中的默认集成环境是 release,换言之,
在我们 Linux 中如果你想发布一个程序,可以直接发布,无需加任何选项。
但是如果你想调试,以 debug 形式发布,那么你就需要在编译时在后面添加一个 -g 选项:
这里输入gcc test_gdb.c -o test_gdb -g -std=c99(重新编译成debug版本),重复上面步骤
现在我们是 debug 版本了,我们也顺理成章地能够使用前面我们说的 list (l)了。

4.1 list/l(显示源代码)
list/l :显示源代码,接着上次的位置往下列,每次列10行。
你也可以l n从第n行开始显示,并且gdb会记录你的上一条指令,直接回车就是上一条指令:

4.2 断点的相关操作
假设我们想在下面代码的第18行处打个断点:
这要是放在 VS 下我们直接滑鼠标选中对应行然后F9就行了
而在 gdb 下打断点的方式是用 breakpoint(简写成b):

此时如果你想查看断点,可以使用 info break(简写成info b)查看你打的断点:
(在这之前先多打两个断点)

删除断点不是要删除断点的行数,而是删除的断点的编号:
delete breakpoints n(简写成d n):删除序号为n的断点

此外还有:(这里不演示了)
disable breakpoints:禁用断点
enable breakpoints:启用断点
4.3 调试的相关操作
开始调试的指令:run(简写成r)
如果我们把场上断点全部干掉了(就是没有断点时),此时按 r 调试程序就会直接跑完:

这里打一个断点在for循环,然后r一下:

如果你想查看变量的内容,我们可以使用 print (简写成p)命令,p 变量名:

如果想逐语句执行(相当于VS的F11),逐语句指令:step(简写成s)

这里发现打印变量不方便演示,
我们在 VS 中调试代码的时候,有时候要观察某个变量时,我们会打开监视窗口,
gdb的监视命令:
display 变量名(监视一个变量,每次停下来都显示它的值)
undisplay 变量名(取消监视一个变量)
如果走到了函数的调用处,不想进入该函数,就不要再按 s 逐语句了。
此时我们应该逐过程执行,我们可以使用 next (简写成n,相当于VS的F10)命令,
当然,此时在函数里面n和s是一样的,这里退出gdb重新进入一下,
然后在16行打断点,r运行,并且顺手演示display 监视:

我们调试的时候在文本特别大的时候我们有时候会跳转,VS 里我们可以直接拖动箭头跳转。
gdb 调试下我们可以使用 until 指令跳转到指定行,(比如在函数内部就能用来跳出函数)
重新退出gdb再进入,打一个断点在18行:

添加监视后的:

当然,你还可以输入 finish,它可以做到直接执行完成一个函数就停下来。
退出重新打断点并监视:

如果想从一个断点跳转至另一个断点,我们可以输入c

4.4 gdb总结
掌握上面单独介绍的 b、d、l、s、n、display、until、r、c、finish 其实就差不多了。
因为我们平时代码出错可以先浏览代码,打printf等查错,最后才用到调试。
上面没讲的gdb的操作用到可以上网查,这里放一张图总结:

本篇完。
下一篇:(开发工具_下)函数库链接+缓存区+实现进度条+Git。