一.软件包管理器------yum
1.软件包的概念
软件包:把一个应用程序运行所需要的二进制可执行文件、配置文件库文件、帮助文件、依赖信息、安装卸载脚本等所有资源打包整合成一个单一的文件,这个文件就是软件包。
在Linux系统下安装文件,一个通常的办法就是下载到程序的源代码,并进行编译,得到可执行程序。但是这种方法太过于麻烦,于是有些人把这些常用的软件提前编译好,做成上述的软件包(类似于Windows操作系统的安装程序)放在一个服务器上,通过包管理器可以很方便的获取到这个编译好的软件包,直接进行安装。这里的软件包和软件包管理器就相当于APP和应用商店的关系。yum便是Linux系统下很常用的软件包管理器。
2.rz sz的概念
rzsz指的是lrzsz开源软件包,是一套基于ZMODEM传输协议的命令行文件传输工具,包含两个核心命令;
- rz:服务器接收文件→本地电脑上传到Linux服务器
- sz:服务器发送文件→Linux服务器下载文件到本地电脑
这个工具用于Windows机器和远端的Linux机器相互的传输文件,安装完毕后,文件可以通过拖拽的方式将文件上传给Linux服务器。
bash
rz # 普通上传
rz -y # -y 覆盖同名文件
上述代码的具体解释:Windows文件上传到Linux服务器,输入上述的命令,会弹出本地文件选择框,把本地文件就会上传到Linux服务器上。这里支持文件的拖拽,将本地电脑的文件直接拖拽到Linux服务器上,可以实现同等的上传效果。
但是这里需要注意的是:打开本地文件选择框,直接选择本地文件夹是不生效的。如果想要上传目录就需要本地电脑先把文件夹压缩成压缩包,rz上传压缩包,服务器再解压。
bash
sz test.c
上述代码的具体解释:sz后面跟着需要下载的文件名,便可以将服务器的指定文件下载到Windows本地电脑上,这里不支持文件的拖拽。
但是这里需要注意的是不能直接传输目录,执行会报错,只能传输文件;如果想要下载目录,就需要服务器先把文件打包,再sz发送压缩包。
3.注意事项
关于yum命令的所有操作都必须保证主机的网络畅通,可以通过以下指令进行验证:
bash
ping www.baidu.com
原因:yum属于前端软件包管理器,作用是从互联网仓库(yum源)下载RPM软件包以及对应的依赖包,之后完成安装、更新、查询等操作。yum绝大数功能都需要访问远程的服务器,因此虚拟机必须能够联通外网/源服务器,网络不通时,yum无法获取软件包和索引信息,命令会执行失败。类似于Windows操作系统下载内容时需要联网一样。
通过上述代码可以检测虚拟机是否联网,下面是联网的虚拟机反馈:

4.查看软件包
通过yum list可以罗列出当前的所有软件包,由于包的数量非常之多,这里需要我们使用grep管道命令筛选出我们关注的包。例如:
bash
yum list | grep lrzsz
结果如下:
bash
lrzsz.x86_64 0.12.20-36.el7 @anaconda

lrzsz指的是软件包的名称;x86_64是CPU架构,64位x86的计算机;0.12.20是软件原始源码的版本号;3是RPM包编译器修订的次数(发行版本);el7指的是CentOS7系统;最后的@anaconda指的是软件已经安装,并且是安装操作系统时,由anaconda系统安装程序预装到系统中的。anaconda类似于"小米应用商店"或者"华为应用商店"。
5.如何安装软件
通过yum,我们可以通过简单的命令完成软件的安装。
语法:yum install +软件名
安装流程:连接yum软件仓库→自动查找lrzsz软件包→自动分析该软件所有依赖包→一并下载软件包与依赖包→自动完成安装
bash
sudo yum install lrzsz
yum会自动找到需要下载的软件包进行下载,如果出现complete的字样说明该软件安装成功。
注意事项:安装软件时由于需要向系统目录写入内容,一般需要root用户才能完成。yum安装软件只能一个一个安装。yum正在安装软件时,尝试安装另一个软件,就会出现报错。
6.如何卸载软件
bash
sudo yum remove lrzsz
如果对安装的软件不满意,就可以对该软件进行删除。删除软件的语法是yum remove+软件名,这样就可以删除该软件了。
二.Linux开发工具
1.vim编辑器的讲解

(1)Linux编辑器---vim的使用
在vim编辑器出现之前,编辑器在历史上也经历了不断的演变:
- ed:Unix最早的编辑器,只能按行进行操作,没有可视化的界面。
- ex:ed的改进版本
- vi:1976年vi作为ex的可视化模式问世,vi是所有类Unix系统默认自带的编辑器,轻便小巧。但是功能简陋,不支持多级撤销、语法高亮、代码缩进
- vim的诞生解决了vi编辑器的痛点,并且兼容了vi编辑器所有的操作。
编辑器是用于创建、查看、修改文本文件的程序软件,它仅处理纯文本内容,不进行编译,不运行程序。常见的文本编辑器有vim、记事本。
下面是早期的键盘画面,可以看到早期的键盘没有上下左右按键,代替上下左右按键的是HJKL,分别表示的是左下上右。这个小彩蛋与下面的vim学习有着紧密的联系:

(2)vim的基本概念
vim有好多种模式,但是学到这里仅需要掌握三种模式即可,分别是命令模式、插入模式、底行模式,各个模式的功能区分如下:
命令模式控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入插入模式下才可以做文字的输入,按esc键可以回到命令行模式,该模式将会被频繁使用;底行模式控制文件的保存或退出,也可以进行文件的替换。在命令行模式下,shift+:可以进入该模式。
(3)vim的基本操作
进入vim全屏编辑画面,默认是正常模式,需要输入a或者i或者o进入插入模式。此时就可以进行内容的插入,如果文件编译结束之后就可以输入指令(shift+:)进入底行模式。最后输入wq表示保存文件内容
(4)vim的正常模式命令集
插入模式
- i:命令模式按i进入插入模式,按下i进入插入模式后是从光标当前位置开始输入内容
- a:按下a进入插入模式后,是从目标光标所在的位置的下一个位置开始输入内容
- o:按下o进入插入模式后,是插入新的一行,从行首位置开始输入文字。
- esc:按下esc按键就会从插入模式变成命令模式
移动光标
- 方位移动:根据古老键盘的铺垫,应该能得出正宗的vim编辑器的左下上右分别是键盘上的按键HJKL
- G:移动到文件内容的最后位置
- $:移动到光标所在行的行尾
- ^:移动到光标所在行的行首
- w:光标跳到下个字/单词的开头
- e:光标跳到下个字/单词的结尾
- b:光标回到上个字/单词的开头
- #|:光标移动到该行的第#个位置,例如13|就是将该行的光标移动到第13个字符位置
- gg:将光标放在整个文件内容的开始位置
- shift+g或者G:将光标放在整个文件的结尾位置
- ctrl+b:屏幕向后移动一页
- ctrl+f:屏幕向前移动一页
- ctrl+u:屏幕向后移动半页
- ctrl+d:屏幕向前移动半页
删除文字
- x:每按一次,删除光标所在位置的一个字符
- #x:表示删除光标所在位置的后面#个字符(包含自己在内)
- X:大写的x,每按一次删除光标所在位置的前一个字符
- #X:删除光标所在位置的前面#个字符(不包括自己)
- dd:删除光标所在行所有的内容
- #dd:从光标所在行开始删除#行
复制文字
- yw:将光标所在之处到字尾部的字符复制到缓冲区
- #yw:复制#个字到缓冲区
- yy:复制光标所在行到缓冲区
- #yy:将光标所在行往下数#行,均进行复制
- p:将缓冲区复制到的内容粘贴到光标所在位置
替换
- r:替换光标所在处的字符
- R:替换光标所到之处的字符,直到按下esc键为止
撤销
- u:撤销到上一次操作的内容,按多次u可以执行多次撤销操作
- ctrl+r:撤销的恢复,类似于返回撤销之前的状态
更改
- cw:更改光标所在位置到字末尾的内容
- c#w:更改光标所在位置到末尾(距离#个字符)的内容
跳行
- ctrl+g:列出光标所在行的行号
- #G:移动光标到内容的第#行的开头
(5)vim底行模式的命令集
在进入底行模式之前,应该先按esc按键进入正常模式,随后就可以使用下方的命令集:
列出行号
set nu:在文件内容的开头显示当前内容所在行的行号
跳行
#:表示跳到文件内容的第#行
查找
- /关键字:先按下/,随后输入需要寻找到字符,如果第一次查到的关键字不是想要的,可以按下n会继续寻找
- ?关键字:先按下?,再输入想寻找的字符。如果第一次查到的关键字不是想要的,可以按下n会继续寻找
保存
w:在冒号后输入w便可以将文件内容保存下来
离开
- q:按下q就会退出,如果无法退出,就给q后面加上一个!强制退出vim
- wq:一般建议搭配w一起使用,这样可以在退出的时候保存文件内容
(6)简单的vim配置
配置文件的位置
在目录/etc/下面,有个名为vimrc的文件,这是系统中公共的vim配置文件,对所有的用户都有效。而在每个用户的主目录下,都可以自己建立配置文件,命名为.vimrc。例如/root目录下,通常已经存在一个.vimrc文件,如果不存在,则就会创建出来一个该名的文件。配置时需要用到vim编辑器,详细的命令为:vim.vimrc
常见的配置选项
syntax on //设置语法高亮
set nu //显示行号
set shiftwidth=4 //设置缩进空格数为4
配置结束后保存并退出,就会得到效果不错的vim编辑器,下面是vim编辑器详细学习的链接:Vim 从入门到精通
2.Linux编译器------gcc/g++的使用
gcc和g++分别用来编译C语言和C++语言,下面是对编译的详细介绍:
(1)编译
编译分为四个阶段:预处理、编译、汇编、链接
下面是四个阶段的详细介绍:
预处理
指令:gcc -E test.c -o test.i
输出:输出一个后缀为i的预处理文件
处理内容:
展开头文件,把头文件内容拷贝在当前文件
宏替换,把宏全部替换成实际文本
删除注释
处理条件编译
不做语法检查,只进行文本替换
编译
指令:gcc -S test.i -o test.s
输出:输出一个后缀为s的汇编语言文件
处理内容:
C语言、语义检查报错出现在编译阶段
翻译成汇编代码,做优化
这里的编译是狭义的编译,不是编译的全过程
汇编
指令:gcc -c test.s -o test.o
输出:输出后缀为o的二进制目标文件
处理内容:将汇编指令翻译成CPU机器码
生成可重定位目标文件,有机器码,但是符号地址没有填写,不能直接运行
其中以o为后缀的文件中包含机器指令、符号表、重定位信息
链接
指令:gcc test.o -o test
输出:可执行的二进制程序
处理内容:
合并多个后缀为o的目标文件
链接系统库
符号重定位:把未确定的函数/变量地址填真实内存地址
生成最终的可执行文件
生成最终可执行文件
(2)gcc的使用
语法格式:
gcc+选项+要编译的文件+选项+目标文件
函数库:
在C语言程序中,本身没有printf等库函数的实现,且在编译中包含的stdio.h文件中也只有该函数的声明,并没有定义函数的实现。那么该函数是在哪里实现的呢?
系统把这些函数实现都安放的库文件中,没有特别指定时,gcc会到系统默认的搜索路径下进行查找,也就是链接到库函数中去,这样就能实现printf函数了,而这就是链接的作用。
函数库指的是将已经编译好的函数代码封装成库文件,提供给别的程序使用,不需要重复书写源代码。提高了代码的书写效率。函数库一般分为静态库和动态库两种。静态库指的是编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时就不需要库文件了。其后缀一般为a。动态库与之相反,在编译链接时并没有将库文件的代码加入到可执行文件中去,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库的后缀一般为.so。
gcc在编译时默认使用动态库,完成了链接之后,gcc就可以生成可执行文件。
拓展:
头文件和库文件的区别?
头文件后缀为h,用于存放函数和宏的声明,供编译器检查语法;
库文件后缀为a或者so,用于存放编译后的二进制机器码,保存函数的真实实现;
#include只引入头文件,还需要链接库文件,程序才能正常运行。
(3)gcc的选项
- -E:只做预处理工作,这个不生成文件,程序员需要把它定向到一个输出文件里
- -S:编译到汇编语言不进行汇编和链接,生成后缀为s的汇编文件
- -c:编译到目标代码,生成后缀为o的目标文件(不执行链接)
- -o#:指定输出文件名为#
- -static:此选项对生成的文件采用静态链接
- -g:生成调试信息,提供给gdb调试器使用
- -shared:此选项将尽量使用动态库,所以生成的文件比较小,但是需要系统由动态库
- -w:不生成任何警告信息
- -Wall:生成所有的警告信息
3.Linux调试器------gdb的使用
(1)背景
在程序发布之前,程序员需要自己进行调试来改正代码存在的一系列问题;在解决完程序员认为的问题后,就将程序交给测试员进行测试。在这两个过程中,程序员自己的调试是代码的debug版本,测试人员使用的程序是和用户使用的一样的release模式。
在Linux操作系统gcc/g++编译后生成的二进制程序,默认是release版本,如果需要gdb调试器进行调试,那么就需要在源代码生成二进制程序的时候加上-g选项。详细请看上面gcc的选项内容。
(2)使用方法
例如我们写一个程序test2.cpp,带着-g选项生成了test2的可执行文件,那么gdb后跟着这个可执行文件,就可以开始代码的调试工作了。
bash
g++ test2.cpp -g -o test2 # -g必不可少
# 启动gdb:传入【可执行文件】,不是 .cpp源码
gdb ./test2
- list或l +行号:显示二进制可执行程序的源代码,第一次l默认显示10行,接着输入l会接着上次的位置往下显示
- list或l +函数名:列出该函数的源代码
- r或run:运行程序
- n或next:单条执行程序
- s或step;进入函数调用,类似于Windows系统的
- break或b +行号:在该行设置断点
- break+函数名:在该函数的开头设置断点
- info或i break :查看断点的信息
- finish:执行到当前函数返回,然后停下来等待命令
- print(p):打印表达式的值,通过表达式可以修改变量的值或调用函数
- p:打印p变量的值
- set var:修改变量var的值
- continue或c:从当前位置开始连续而非单步执行程序
- delete breakpoints:删除所有的断点
- delete breakpoints +序号:删除该序号的断点
- disable breakpoints:禁用断点
- enable breakpoints:启用断点
- display+变量名:跟踪查看一个变量,每次停下来都显示该变量的值
- undisplay:取消对先前设置的变量的跟踪
- until+行号:跳到该行
- breaktrace或bt:查看各级函数调用及参数
- info或i locals:查看当前栈局部变量的值
- quit或q:退出调试
4.Linux项目自动化构建工具------make/makefile
(1)介绍
当项目很多包含很多.c.cpp文件时,每次手写好多g++命令很麻烦,完成makefile就可以直接输入make指令进行自动编译。
makefile命令可以使工程完成自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具。make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化的构建。
makefile配置文件语法:
bash
目标:依赖文件
命令 # ⚠️命令前面必须是【Tab键】,不能用空格!
目标指的是要生成的文件;依赖文件指的是生成目标文件需要哪些源文件;命令指的是相关的编译命令,首行必须进行Tab缩进(否则会出现报错)
(2)实例
cpp
#include <stdio.h>
int main()
{
printf("hello Makefile!\n");
return 0;
}
下面来配置makefile文件:
bash
hello:hello.o
gcc hello.o -o hello
hello.o:hello.s
gcc -c hello.s -o hello.o
hello.s:hello.i
gcc -S hello.i -o hello.s
hello.i:hello.c
gcc -E hello.c -o hello.i
.PHONY:clean
clean:
rm -f hello.i hello.s hello.o hello
clean是动作,表示的是对文件的删除动作,不是生成文件,如果目录下恰好有个文件名叫clean,make 会误以为已经完成,不执行删除。用.PHONY声明伪目标就可以解决该问题。
配置完makefile文件之后,就可以直接使用make命令进行文件的编译;使用make clean命令进行文件的删除。
(3)依赖关系
上面的makefile文件中,hello文件依赖于hello.o文件;hello.o文件依赖于hello.s文件;hello.s文件依赖于hello.i文件;hello.i文件依赖于hello.c文件。上面的配置方法略显得繁琐,可以省略中间的过程,直接得出hello文件依赖于hello.c文件即可。
(4)依赖方法
make会比较目标文件和依赖文件的修改时间来判断是否进行编译。目标不存在,则执行编译;依赖文件修改时间比目标文件新,则重新编译;目标存在,依赖全部没有更新,则不执行编译。
(5)make命令的原理
- make命令在当前目录查找makefile的文件
- 解析文件内的规则:目标文件和依赖关系
- 从第一个目标文件开始作为最终的目标文件,递归检查该文件的所有依赖关系
- 判断是否执行该规则下的命令(详细请看下方解释)
- 递归处理,生成高层目标前,先把它所依赖的子目标全部处理完成
判断方法:
- 目标文件不存在--->执行命令生成目标
- 某个依赖文件的修改时间晚于目标文件--->执行命令,重新生成目标
- 目标存在,且所有的依赖都比目标的修改时间晚--->不执行任何命令
核心思想:只重新编译发生改动的文件,不编译全部文件,提升编译的效率
原因:
没有make命令时,项目一旦规模过大。每次修改代码,即使修改了一个文件也需要全部进行编译。项目文件过多就会导致编译速度变慢,浪费CPU的资源和时间;如果只编译修改的文件,需要人为牢记依赖关系,文件规模过大会导致记错或重复编译。
make编译的这套极致可以解决两个核心痛点:避免全量重复编译,节省编译时间(只编译被修改过的文件);自动化管理依赖关系,不用人记编译命令。
make命令怎么知道文件被修改了呢?
通过对比文件的修改时间,如果依赖文件的修改时间比目标文件新,则重新编译;依赖文件时间旧(文件没被修改)就不会进行编译。
(6)项目清理
编译项目之后会产生很多中间产物,比如.o的目标文件或可执行程序。所以需要对这些文件进行清理。项目清理需要做到把编译生成的文件删掉,回到源码的原始状态。手动删除过于麻烦,就有了makefile文件配置项目清理。clean不会自动执行,必须手动输入make clean;make 默认执行第一个目标,不会执行clean指令,且只删除编译产物,不会删除.cpp或.h的源代码。
三.Linux第一个程序------进度条
1.回车和换行
(1)换行
换行指的是将光标向下移动一行,光标的横向位置不发生改变。用符号表示为\n
(2)回车
回车指的是将光标移动到该行的开头,光标的纵向位置不发生改变。用符号表示为\r
(3)注意事项
很多人将\n等同于回车,这是不对的!Linux系统把\n同时实现到行首和下一行的两个效果,这是系统的封装,但是不等于\n就是回车本身。
2.行缓冲区
prinf输出不是直接打印在屏幕上,而是先放在行缓冲区中,满足条件才刷新输出到屏幕上。
刷新缓冲区的条件:
- 遇到换行 \n(行缓冲最常见)
- 程序正常结束 return 0;
- 缓冲区满
- 手动调用 fflush(stdout)属于强制刷新缓冲区;
stdout默认是行缓冲模式,没有\n,内容留在缓冲区,屏幕看不到输出。
下面是对缓冲区的验证:
cpp
#include <stdio.h>
int main()
{
printf("hello");
// 没有\n,hello还留在缓冲区,不会打印
while(1); //死循环,程序不会结束,屏幕啥也不显示
return 0;
}
cpp
#include <stdio.h>
int main()
{
printf("hello\n"); // \n 刷新行缓冲区,直接打印
while(1);
return 0;
}
cpp
#include <stdio.h>
int main()
{
printf("hello");
fflush(stdout); //强制把stdout缓冲区内容刷到屏幕
while(1);
return 0;
}
3.代码实践
cpp
#include <stdio.h>
#include <string.h>
int main()
{
int i = 0;
char bar[102];
memset(bar, 0, sizeof(bar));
const char* lable = "|/-\\";
while (i <= 100)
{
printf("[%-100s][%d%%][%c]\r", bar, i, lable[i % 4]);
fflush(stdout); //强制刷新缓冲区
bar[i++] = '#'; //进度条的图案
Sleep(10); //每个进度条间隔
}
printf("\n");
return 0;
}
因为进度条应该是从左到右的动态效果,所以应该用\r,并非\n不能刷新行缓冲区,所以需要fflush函数来手动刷新缓冲区,这样就能达到进度条的效果
四.代码管理------git
1.安装git
bash
yum install git
2.GitHub项目的创建
-
首先创建账户,随后进行登录
-
登陆成功后,进入个人主页后点击左上方的new选项

-
输入相关的仓库名,随后写上仓库的解释,最后点击右下角的创建即可

-
在创建好仓库之后,保存好HTTPS的链接,以备接下来的下载

-
打开虚拟机,下载项目到本地。

3.代码上传三板斧
1.将代码放在刚才下载好的目录中
bash
git add 文件名
2.提交改动到本地
bash
git commit .
# .表示当前目录,提交时应该注意书写相关提交日志
3.同步到远端服务器,需要输入git的密码,随后就上传成功了
bash
git push