🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。
🚁 个人主页:不 良
🔥 系列专栏:🛹Linux 🛸C++
📕 学习格言:博观而约取,厚积而薄发
🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与诸君一同成长! 🌹
文章目录
- Linux软件包管理器——yum
- yum简介
- yum的使用
- yum源
- Linux编辑器——vim
- vim基本概念
- vim 命令模式命令集
- vim末行(底行)模式命令集
- vim的配置
- Linux编译器——gcc/g++
- gcc/g++的作用
- gcc/g++过程分析
- 预处理
- 编译
- 汇编
- 链接
- 动静态库
- Linux调试器——gdb
- gdb调试命令汇总
- 实例调试
- Linux自动化构建工具——make/Makefile
- 依赖关系和依赖方法
- make/Makefile的使用
- sudo提升权限
- Linux小程序——进度条
- 缓冲区的概念
- \r和\n
- 倒计时小程序
- 进度条小程序
- git命令行的使用
- 在Linux上使用git
Linux软件包管理器——yum
yum简介
我们平时在手机上安装软件都需要先去应用商店搜索,找到想要的软件下载并且安装,有些手机也支持在应用商店里卸载软件,yum就相当于手机上的应用商店,在联网的情况下可以通过yum的相关指令搜索软件包,下载安装并且可以卸载。
yum的使用
搜索指令——yum list | grep 软件包名称
当我们想使用yum查看一共有哪些软件包的时候可以通过yum list
指令,但是往往软件包非常多,所以我们可以通过yum list | grep 软件包名称
指令查找我们想要的软件包。如下图我们想安装sl
软件包,可以通过yum list | grep sl
指令搜索。
说明:
搜索列表中出现的以这种形式展现:软件包名称.系统安装包 主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构 提供者。如上面搜索的
sl.x86_64
中,sl是软件包名称。
x86_64
后缀表示64位系统的安装包,i686
后缀表示32位系统安装包,选择包时要和系统匹配。“el7” 表示操作系统发行版的版本,“el7” 表示的是 centos7/redhat7。
最后一列,base 表示的是 “软件源” 的名称, 也就是软件包的提供者。
安装指令——yum -y install 软件包名称/yum install -y 软件包名称
当我们通过搜索指令找到自己要安装的软件包之后,可以在root用户下通过指令yum -y install 软件包名称
进行安装,普通用户需要使用sudo yum -y install 软件包名称
,如下图我们要安装sl
软件包,可以使用yum -y install sl.x86_64
指令。
当出现Complete时安装完成,运行sl
指令查看是否能够运行,运行情况如下图。
卸载指令——yum -y remove 软件包名称/yum remove -y 软件包名称
当我们不再使用该软件时,可以在root用户下通过指令yum -y remove 软件包名称
进行卸载,普通用户需要使用sudo yum -y remove 软件包名称
,如下图我们使用yum -y remove sl.x86_64
卸载sl
。
注意事项:
1.一个服务器同一时刻只允许一个yum进行安装,不能在同一时刻同时安装多个软件。
2.安装软件时由于需要向系统目录中写入内容,普通用户需要
sudo
指令提升权限或者在root用户下才能进行安装。
3.上面指令中的
-y
表示直接安装不再进行交互询问,可以不加-y
,此时进行交互询问,键入y之后进行安装。
yum三板斧:
1、搜索指令——yum list | grep 软件包名称
2、安装指令——yum -y install 软件包名称/yum install -y 软件包名称
3、卸载指令——yum -y remove 软件包名称/yum remove -y 软件包名称
yum源
当我们使用yum指令进行搜索安装的时候,它是怎么知道要去哪里下载的呢?这是因为yum有自己的配置文件(内置下载链接的地址)——yum源。
下图中我们可以看到yum源仓库及仓库中大量的下载链接,repo就是仓库的简写。
我们可以尝试更改配置yum源步骤:
1.先备份老的yum源CentOS-Base.repo(保证尝试配置失败时可以恢复);
2.通过指令
wget yum源链接
获取新的yum源配置文件;
3.因为系统默认回到CentoS-Base.repo这个仓库中去寻找地址下载软件,所以通过
mv
指令将新的yum源重命名成为CentOS-Base.repo;
4.运行
yum clean all && yum makecache
指令,使其生效。如果想安装的软件找不到有可能就是在扩展yum源
epel.repo
中,此时在root用户下或者使用sudo指令提升权限,运行yum install -y epel-release
指令系统会根据你的base yum源,帮我们找到和他匹配的扩展yum源,此时再执行安装程序就行。
扩展:实现本地机器和云服务器之间的文件互传
指令
rz -E
:可选择本地机器上的文件上传到云服务器。指令
sz + 文件名
:可以选择云服务器上的文件下载到本地机器的指定文件夹中。
Linux编辑器——vim
vim基本概念
vim是一款多模式的编辑器,大多数情况下用来编辑代码,如果没有安装vim可以使用sudo yum install -y vim
或者在root用户下运行yum install -y vim
安装vim。我们最常用的模式有以下三种:
1.正常/普通/命令模式(Normal mode)
默认打开的时候vim处于命令模式,此时我们可以通过相关的指令来控制屏幕光标的移动,字符、字或行的删除,移动复制等操作,可以通过键盘上i
进入插入模式。
2.插入模式(Insert mode)
只有插入模式下,我们才可以进行代码的编辑,按ESC
键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。
3.末行/底行模式(last line mode)
文件保存或退出,列出行号等操作。 在命令模式下,shift+;
即可进入该模式,在底行模式下输入q
退出vim编辑器。
模式之间的切换:命令模式切换插入模式在键盘上直接按i
,退出插入模式按ESC
键;命令模式切换底行模式按下shift
和;
,退出底行模式按ESC
;底行模式和插入模式之间不能切换。注意不同模式之间的切换需要在输入法为英文模式下进行切换。
vim 命令模式命令集
刚进入vim时处于命令模式,此时我们可以通过以下命令进行相应的操作。
- 命令模式切换为插入模式
i
:进入插入模式后,按“i”进入插入模式后是从光标当前位置开始输入文件;
s
:删除一位后进入插入模式;
a
:进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字;
o
:进入插入模式后,是插入新的一行,从行首开始输入文字;
- 移动光标:
vim可以直接用键盘上的上下左右键移动,但正规的vim是用小写英文字母h、j、k、l
,分别控制光标左、下、上、右移一格 ;
按[gg]:将光标定位到文档的最开始
按「G」:将光标定位到文档最结尾
按「$」:移动到光标所在行的行尾
按「^」:移动到光标所在行的行首
按「w」:光标跳到下个字的开头
按「e」:光标跳到下个字的字尾
按「b」:光标回到上个字的开头
按「#l」:光标移到该行的第#个位置,如:5l,56l
按[shift+g]:进入文本末端
按「ctrl」+「b」:屏幕往“后”移动一页
按「ctrl」+「f」:屏幕往“前”移动一页
按「ctrl」+「u」:屏幕往“后”移动半页
按「ctrl」+「d」:屏幕往“前”移动半页
- 删除文字:
「x」:每按一次,删除光标所在位置的一个字符
「#x」:例如,「6x」表示删除光标所在位置的“后面(包含自己在内)”6个字符
「X」:大写的X,每按一次,删除光标所在位置的“前面”一个字符
「#X」:例如,「20X」表示删除光标所在位置的“前面”20个字符
「dd」:删除光标所在行
「#dd」:从光标所在行开始删除#行
- 复制:
「yw」:将光标所在之处到字尾的字符复制到缓冲区中。
「#yw」:复制#个字到缓冲区
「yy」:复制光标所在行到缓冲区。
「#yy」:例如,「6yy」表示拷贝从光标所在的该行往下数6行文字。
「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与y有关的复制命令都必须与p配合才能完成复制与粘贴功能,同时使用[dd]删除的指令也可以使用p指令粘贴。
- 替换:
「r」:替换光标所在处的字符。
「shift」+ 「r」:进入替换模式,替换光标所在位置,替换之后不想要可以删除,删除之后恢复成之前的字符。完成之后「ESC」进入命令模式。
「shift」+ 「~」:在光标处快速进行大小写切换。
- 撤销上一次操作:
「u」:如果您误执行一个命令,可以马上按下「u」,回到上一个操作。按多次“u”可以执行多次回复。
「ctrl + r」: 撤销的恢复。
- 更改:
「cw」:更改光标所在处的字到字尾处
「c#w」:例如,「c3w」表示更改3个字
- 跳至指定的行:
「ctrl」+「g」列出光标所在行的行号。
「#G」:例如,「15G」,表示移动光标至文章的第15行行首。
vim末行(底行)模式命令集
在使用末行模式之前,请记住先按「ESC」键确定您已经处于正常/命令模式,再按shift + ;
即可进入底行模式。
- 列出行号:
「set nu」: 输入「set nu」后,会在文件中的每一行前面列出行号。
- 取消行号:
「set nonu」: 输入「set nonu」后,会将文件中的每一行前面的行号取消。
- 跳到文件中的某一行:
「#」:「#」号表示一个数字,在冒号后输入一个数字,再按回车键就会跳到该行了,如输入数字15,再回车,就会跳到文章的第15行。
- 查找字符:
「/关键字」: 先按「/」键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直按「n」会往后寻找到您要的关键字为止。
「?关键字」:先按「?」键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直按「n」会往前寻找到您要的关键字为止。
两者的区别是:[/关键字]是从文件顶部开始向下找,而「?关键字」是从文件底部开始向上找。
「w」: 在冒号输入字母「w」就可以将文件保存起来
- 分屏指令:
「vs 文件名」:实现多文件的编辑,在vim分屏模式下,光标在哪里,我们就在编写哪一个文件。
「ctrl+ww」:连续按两次w,切换光标到不同的界面。退出时光标在哪一个界面退出的就是哪一个文件。
- 执行指令:
「!+指令」:在不退出vim的情况下,可以在指令前面加上「!」就可以执行Linux的指令,例如查看目录、编译当前代码等。
- 离开vim:
「q」:按「q」就是退出,如果无法离开vim,可以在「q」后跟一个「!」即输入「q!」强制离开vim。
「wq」:一般建议离开时,搭配「w」一起使用,这样在退出的时候还可以保存文件。
注意事项:
1.如果你不知道自己在什么模式下,可以无脑ESC
,确保自己在命令模式下,命令模式下可以切换到其他模式。
2.退出的时候一般都是先保存再退出,底行模式下输入wq指令。
3.在vim中操作不要用鼠标和鼠标的滑轮。
vim的配置
a.自己配置(不推荐)
vim在启动的时候,会自动在当前用户的目录下,寻找配置文件,如果没有就是默认。
在目录/etc/下面,有个名为vimrc的文件,这是系统中公共的配置文件,对所有用户都有效。
在每个用户的主目录/home/x下,都可以自己建立私有的配置文件,命名为.vimrc
,这是该用户私有的配置文件,仅对该用户有效.一个用户一个vim配置,我们所做的配置不会影响其他人。
先创建一个文件:.vimrc
,创建的配置文件都在这个文件中,配置即刻生效,如我们自己创建的配置文件中设置行号:
不想使用的时候也可以通过双引号注释掉:
b.自动配置(推荐)
我们这里推荐的方法就是直接执行以下指令(想在哪个用户下让vim配置生效,就在哪个用户下执行该指令,不推荐直接在root下执行):
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh
在普通用户下安装,要按照提示输入root密码:
在root用户下安装不需要输入密码,直接安装完成:安装成功之后需要按照命令提示操作,才能成功使用配置文件,需要退出用户登录或者输入source ~/.bashrc
命令。
我们选择输入source ~/.bashrc
命令,输入之后配置就生效了。
生效之后我们再进入vim编辑器:我们会发现自动补全、行号显示以及自动缩进等功能都有了。
当我们不想使用的时候也可以选择卸载:在安装了VimForCpp的用户下执行:bash ~/.VimForCpp/uninstall.sh
就可以完成卸载。
Linux编译器——gcc/g++
通过前面的学习我们知道编译过程由以下四个步骤:
1、预处理:头文件展开、条件编译、宏替换、去注释等,C语言经过预处理之后还是C语言;
2、编译:词性、语义分析、符号汇总等,编译的过程是将C语言转换成汇编语言;
3、汇编:生成符号表等,汇编的过程是将汇编语言转变成为可重定位的目标二进制文件,该文件不可以被执行,最后形成.obj
文件(windows下),;
4、链接:符号表汇总等,将我们自己形成的.obj
文件和库文件进行某种合并,形成可执行程序。
gcc/g++的作用
gcc专门用来编译C语言的,g++专门用来编译C++的,当我们在Linux下创建一个.c
文件之后,可以通过gcc编译生成a.out
可执行文件:
可以通过gcc -o
设定要生成的目标文件的名称,-o
选项后面跟的一定是要生成文件的名称。上面的test.c文件我们想生成test可执行文件可以写成gcc -o test test.c
或者gcc test.c -o test
。比较推荐的是gcc test.c -o test
:
gcc/g++过程分析
程序的翻译主要分为编译和链接,编译又可以分为预处理、编译、汇编
常用选项:
-E:从当前文件(.c
文件开始)开始,进行程序的翻译,预处理做完就停止,预处理之后的文件习惯称为.i
文件。
-S:从当前文件开始(可以从.c
文件开始翻译,也可以从.i
文件开始翻译),进行程序的翻译,当编译完成就停下来,编译后的文件通常以.s
作为后缀,通常.s
作为汇编文件的后缀
-c:从当前文件开始,进行程序的翻译,做完汇编就停止,生成的文件我们一般加后缀.o
,.o
对等于windows中的.obj
。
预处理
- 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
- 预处理指令是以#号开头的代码行。
- 选项
-E
,该选项的作用是让gcc在预处理结束后停止编译过程。 - 选项
-o
是指目标文件,.i
文件为已经预处理过的C原始程序 - 举例
cc
-E:从当前文件(.c
文件开始)开始,进行程序的翻译,预处理做完就停止,预处理之后的文件习惯称为.i
文件。
如上图所示,当我们直接使用gcc -E 目标文件
(这里我们测试用例使用的是test.c文件),会将执行结果直接打印在屏幕上,所以我们可以使用-o
选项指定文件名称,假设我们要生成的文件名称是test.i
文件:
然后我们再对比一下:
test.i就是预处理之后形成的临时文件,我们可以在test.i文件中可以看到头文件展开和宏替换,.i
文件还是C语言。
编译
- 在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后gcc把代码翻译成汇编语言。
- 用户可以使用
-S
选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。 - 举例
gcc -S test.i -o test.s
-S:从当前文件开始(可以从.c
文件开始翻译,也可以从.i
文件开始翻译),进行程序的翻译,当编译完成就停下来,编译后的文件通常以.s
作为后缀,通常.s
作为汇编文件的后缀。
打开之后就是汇编语言:
汇编
- 汇编阶段是把编译阶段生成的
.s
文件转成目标文件.o
。 - 使用选项
-c
可以看到汇编代码转化为.o
的二进制目标代码 - 举例:
gcc –c test.s –o test.o
-c:从当前文件开始,进行程序的翻译,做完汇编就停止,生成的文件我们一般加后缀.o
,.o
对等于windows中的.obj
。
打开文件之后就是:
不能执行该文件,即便添加权限也不能执行:
说明.o和.obj文化都是不可以执行的。
链接
-
在成功编译之后,就进入了链接阶段
-
举例:
gcc test.o -o test
链接后生成的也是二进制文件。
动静态库
我们为什么能够在Linux下进行C、C++代码的编写呢?
Linux系统默认已经携带了语言级别的头文件和文件对应的库。
在Linux中库存放在哪里呢?存放在 /usr/include中:
命令:ldd + 可执行程序文件名
可以查找链接库的的位置:
去掉前缀lib,后缀.a或者.so,中间剩下的就是库的名字,上面面库的名称就是c-2.17。
库分两种(库本质也是一种文件):
1、静态库:一般是以lib开头,以.a
结尾,如libxxx.a
2、动态库:一般是以lib开头,以.so
结尾,如libxxx.so
上面两点是Linux下特有的动静态库划分;Windows下的静态库后缀为.lib
,动态库后缀.dll
,原理相似。
我们安装VS2022、VS2019的时候最重要的一个工作是什么?帮我们下载并安装语言的头文件和库文件。
我们用的指令有相当一部分都是用C语言写的。如何看待指令呢?指令就是程序、工具、指令,在Linux下一切皆文件。
动静态库:
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件当中,因此生成的文件比较大,但在运行时也就不再需要库文件了,静态库一般以
.a
为后缀。 - 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件当中,而是在程序运行时由链接文件加载库,这样可以节省系统的开销,动态库一般以
.so
为后缀。如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。
动静态链接:
- 静态链接:将你所需要的代码拷贝到你的程序中,使用静态链接即使库不存在了也不影响程序的执行。
- 动态链接:将你所需要的方法的地址拷贝到你的程序中。动态库所谓的链接的过程就是把我们所要用的方法对应的地址(调用函数的地址)拷贝进我们的程序里,这个工作就叫做链接。
动态库==共享库,凡是共享的只需要一份就行。当共享库被删除所有依赖共享库的都将无法使用。
总结:
1.所有库分为静态库(专门让编译器对用户的程序进行静态链接的)和动态库(专门让编译器对用户的程序进行动态链接的)。
2.静态库和静态链接:链接的时候,如果是静态链接,找到静态库,拷贝静态库中的我所需要的代码到我自己的可执行程序中。
3.动态库和动态链接:链接的时候,如果是动态链接,找到动态库,拷贝动态库中的我所需要的代码的地址到我自己的可执行程序中相关的位置。
4.静态链接成功:我们的程序不依赖任何库,自己就可以独立运行。
5.动态链接成功:我们的程序还是依赖动态库,一旦动态库缺失,我们的程序便无法运行。
6.静态库的缺点:因为自身拷贝的问题,比较浪费空间。
7.动态库的优点:因为可以做到被大家共享方法,所以真正的实现永远都是在库中,程序内部只有地址,比较节省空间。
8.静态库vs动态库:Linux默认使用的是动态链接和动态库。
怎么判断是动态库还是静态库?
file
指令后面跟上文件名,根据说明判断是否是动态链接,使用的是共享库。
如果进行静态链接呢?在gcc进行编译时在后面加上-static
选项,一般的云服务器默认都是只有动态库,如果在进行C语言和C++静态链接时可能会出现如下报错:
此时可以通过命令yum install -y glibc-static
安装C静态库,也可以通过yum install glibc-static libstdc++-static -y
或者yum -y install glibc-static libstdc++-static
同时安装C和C++的静态库:
此时再查看文件类型时就会发现显示静态链接:
我们可以观察一下两种不同链接方式生成的文件大小:
充分证明了动态链接比静态链接更加节省空间。
Linux调试器——gdb
程序的发布方式有两种:debug模式和release模式;Linux下gcc/g++编译出来的二进制程序,默认是release模式,但是如果要使用gdb调试必须是在debug模式下,所以必须在源代码生成二进制程序的时候在后面加上-g
选项保证是debug模式。
gdb调试命令汇总
进入gdb:
指令: gdb 文件名
调试:
1)「run/r」:运行代码(启动调试)。
2)「next/n」:逐过程调试。
3)「step/s」:逐语句调试。
4)「until 行号」:跳转至指定行。
5)「finish」:执行完当前正在调用的函数后停下来(不能是主函数)。
6)「continue/c」:运行到下一个断点处。
7)「set var 变量=x」:修改变量的值为x。
显示:
1)「list/l n」:显示从第n行开始的源代码,每次显示10行,若n未给出则默认从上次的位置往下显示。
2)「list/l 函数名」:显示该函数的源代码。
3)「print/p 变量」:打印变量的值。
4)「print/p &变量」:打印变量的地址。
5)「print/p 表达式」:打印表达式的值,通过表达式可以修改变量的值。
6)「display 变量」:将变量加入常显示(每次停下来都显示它的值)。
7)「display &变量」:将变量的地址加入常显示。
8)「undisplay 编号」:取消指定编号变量的常显示。
9)「bt」:查看各级函数调用及参数。
10)「info/i locals」:查看当前栈帧当中局部变量的值。
断点:
1)「break/b n」:在第n行设置断点。
2)「break/b 函数名」:在某函数体内第一行设置断点。
3)「info breakpoint/b」:查看已打断点信息。
4)「delete/d 编号」:删除指定编号的断点。
5)「disable 编号」:禁用指定编号的断点。
6)「enable 编号」:启用指定编号的断点。
退出gdb:
1)「quit/q」:退出gdb。
实例调试
我们在Linux下通过下面的代码来更加详细的认识这些操作:
当我们使用gcc test.c -o test
编译运行的时候会出现如下报错:
这是因为在for循环里初始化,是C99之后才能支持的,所以我们要在指令的后面加上 -std=c99
或者-std=gnu99
才可以:
当我们想使用gdb调试的时候怎么调试呢?
当我们直接使用gdb加上可执行程序名时会出现如下报错信息:
这是因为Linux下默认生成的是release版本的,而release不能用来调试,要在debug版本下进行调试,我们可以使用quit或q指令离开上述调试界面,在编译程序的时候添加-g
选项可以使其为debug模式,-g
:让gcc、g++以debug方式调试:
为什么debug能调试,release不能调试?因为release是客户使用的,不加调试信息,体积相对较小。
读取可执行程序的二进制构成用readelf -S
指令,Linux形成的可执行程序遵守的二进制规则是elf
格式。
搜索调试信息:
gdb调试test,(gdb)后可以直接输入指令:
l 0
或者l 1
(这里的l也可以替换成L)可以从第0行或者第1行开始查看代码信息,随后直接按enter就可以往下查看。l这个命令是list的简写:
输入指令r
进行调试,此时还没有打断点,直接执行完毕,正常执行正常退出:
指令b 行号
,设置断点,b后面跟的是行号:
查看断点指令:info b
,其中Num表示的是断点编号:
再次运行r
指令,在断点处停止,方便进行单步调试:
再次查看断点info b,提示当前断点已经被命中一次:
删除断点d 断点编号
,d后面跟断点编号,删除之后输入info b
查看发现当前无断点:
输入r, 会提示是否从开始处运行,选择n,即继续向下调试;选择y就是从头开始:
再次创建断点并且运行:编号是2,没有退出gdb,num编号依次递增:
使能:不删除断点,让断点失去作用。在VS中右击断点可以看到关闭(实心变空心),输入disable breakpoint 断点编号
或者disable 断点编号
设置空断点,输入enable 断点编号
使断点恢复作用:
打断点我们也可以使用b + 函数名(文件名:函数名)
或者b 文件名:行数
:
在VS下:
逐过程(F10):以函数为单位不进入函数,跳过函数。
逐语句(F11):有函数进入函数。
gdb下类似于逐过程:用指令n(next也可以);逐语句:s(step也可以)指令进入函数。gdb会记住上一次的指令,所以我们可以直接按回车执行上一次输入的指令:
监视可以用p 变量
指令:
想要一直看到变量变化,可以用display 变量
指令:常显示(内置类型,结构体等自定义类型,stl等);
取消常显示,undisplay + 前面显示的编号
才能够取消,如果加undisplay sum 不能取消:
执行到把循环跑完,可以直接用until + 预期行数
。下图中10显示的是预期要到的行数(在函数内,进行指定位置的跳转,执行完区间代码):
当函数嵌套调用时可以查看压栈的过程,使用bt指令,最下面的就是最先执行的:
finish指令:进入一个函数,只执行完该函数就停下(进入函数后):
从一个断点到另一个断点,使用c(continue)指令,下图中是在第15行和第17行打断(从一个断点运行至下一个断点):
set var
指令 :设置变量为某个值,下图中为设置变量i等于20:
调试器:核心工作是为了定位问题。所有查看内容的指令,并不影响实际调试指令。
Linux自动化构建工具——make/Makefile
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
- makefile带来的好处就是——自动化编译,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,makefile通常在当前的源代码路径下,两个搭配使用,完成项目自动化构建。
依赖关系和依赖方法
依赖关系: 文件A的变更会影响到文件B,那么就称文件B依赖于文件A。
例如,test.i文件是由test.c文件预处理之后得到的,那么test.c文件的改变会影响test.i文件,所以test.i文件依赖于test.c文件。
依赖方法: 如果文件B依赖于文件A,那么通过文件A得到文件B的方法,就是文件B依赖于文件A的依赖方法。
例如,test.i依赖于test.c,而test.c需要通过gcc -E test.c -o test.i指令得到test.i,那么test.i依赖于test.c的依赖方法就是gcc -E test.c -o test.o。
make/Makefile的使用
之前当我们需要编译文件的时候我们通常是直接输入gcc指令生成可执行程序:
但是我们可以直接使用Makefile文件,先创建一个Makefile文件,在里面编辑如下,test依赖于test.c,依赖方法为gcc test.c -o test
:
第一行中,我们要用test.c形成test,通常我们把这组关系叫做依赖关系。
第二行我们叫做依赖方法。makefile是一个围绕依赖关系和依赖方法构建的一个自动化编译的工具,完成一件事情必须有正确的依赖关系和依赖方法。
make
命令使其能够运行makefile文件中的内容:
可以通过rm指令删除test可执行文件,也可以通过在Makefile文件中进行语句的定义之后调用命令进行清理:
执行make clean
指令:
下图中按照编译的顺序进行操作,第一行中由test.o文件形成test文件,但是因为没有test.o文件,所以向下看……,这里就好像是栈,上面的依赖关系先入栈,然后再慢慢出栈。
Makefile文件中显示的是下面这样,但是在make执行时是先执行最下面的。
通常不用这个方法写。
Makefile中的简写方式:
- $@:表示依赖关系中的目标文件(冒号左侧)。
- $^:表示依赖关系中的依赖文件列表(冒号右侧的所有文件)。
- $<:表示依赖关系中的第一个依赖文件(冒号右侧第一个)。
**依赖关系中目标文件对应的依赖文件列表可以是空。:
前是目标文件,:
后面的是目标文件列表。 **
清理:
为什么make 后面要加上clean,而执行test时不需要呢?因为Makefile默认执行第一组依赖关系和依赖方法。我们也可以在执行make的时候在后面加上test,当我们把clean放到第一组的位置上,默认执行的就是clean。
make就是给Makefile制作的一个命令。
上图意思是test文件已经是最新的了,不需要进行编译了。这也说明了test文件不是总是被执行的。
关键字:.PHONY
:总是被执行的,一般用.PHONY
修饰的符号称为伪目标,特征就是总是被执行的。 一般将clean的目标文件设置为伪目标。
我们通过给第一组依赖关系加上.PHONY
来验证:
不建议给目标文件加关键字.PHONY
。
上面执行时为什么make会知道这是最新的?
通过对比源代码和可执行程序的时间:
Modify时间:可以通过touch源文件的方式在不更改源代码的情况下改变Modify时间:
sudo提升权限
当我们使用sudo命令提升指令权限时,输入密码后提示:当前的用户不在系统的信任列表里:
要是想使用sudo命令,首先要将用户添加到信任名单,信任名单在etc下的sudoers中,权限限制,需要root用户才能添加:
在root用户下打开,root用户不受权限约束:
上面的内容不管,我们直接找到上图所示的地方,然后yy复制,p粘贴,将名字修改为想要提升权限的用户名:
但是在最下面还是会有下列提示信息:此时我们在w后面加上!就可以保存。此时就将用户添加信任列表里:
此时再执行sudo指令就可以提升权限了,当用户登录的时候不能删除该用户。
Linux小程序——进度条
缓冲区的概念
我们先在Linux上执行下面的代码:
执行结果:
当我们将代码修改为下面这样:
执行结果为:
两份代码的区别就是在printf打印时\n
的区别,打印结果不相同证明了缓冲区的概念。
我们需要知道显示器对应的是行刷新,只有在缓冲区遇到\n
或是缓冲区被写满,或者程序结束时缓冲区内容才会被打印出来,而在第二份代码当中并没有\n
,所以字符串Hello demo先被写到缓冲区,休眠3秒之后,直到程序运行结束才将Hello demo打印到显示器当中。
那如果不使用\n
进行换行怎么刷新缓冲区?可以使用fflush函数(头文件是stdio.h),该函数可以刷新缓冲区。
运行结果:
\r和\n
\r: 回车,使光标回到本行行首。
\n: 换行,使光标下移一格。
观察下面代码:
运行结果:
当我们将上面的代码修改为下面的代码时就会被覆盖,原因就是\r把光标放在最开始,把打印出的内容给覆盖了:
执行结果:
\r
不会刷新缓冲区。
倒计时小程序
我们可以利用\r
的特性写一个倒计时小程序:
利用\r
的特点让每次输出的内容都从行首开始打印,运行结果:
进度条小程序
进度条小程序代码:
当想在进度条后面提示%多少时候,可以加如下代码,%符号在输出的时候可以用%%符号来表示。
运行结果:
C语言也可以输出彩色:
也可以将代码修改一下,给进度条加上颜色:
打印结果:
git命令行的使用
git是开源、去中心化、分布式的;git能够进行版本管理:在更新的同时,保存之前的版本,就是版本管理(版本号,可以根据标签分组)。
git --version
命令,用来查看当前git版本。
如果没有安装,可以使用yum install -y git
进行安装,要注意需要在root用户下进行安装。
我们在Gitee官网建好仓库:
创建成功之后,在管理最下面开源(空仓库不允许开源),还可以添加开发人员。
在Linux上使用git
我们在一个新建的测试目录下进行测试:
先复制链接,然后git clone + 链接
,把远端仓库的所有内容克隆过来,因为现在是私有仓库,需要输入用户名和密码,开源仓库可以直接拷贝。
把远端仓库克隆下来之后,cd进入仓库(如果此时不小心把仓库删掉了,再克隆就可以了,删本地不影响远端):
查看REMADE.md:
什么是仓库?就是.git
目录,.git
就是仓库,里面包含各种各样的文件,object下有版本号:
要注意不能修改.git名字。
将目标文件拷贝到当前git目录下:
当前只是把文件拷贝到了本地的目录当中,并没有把文件添加到仓库中。
.
就是把当前目录下所有没被添加的文件添加到仓库中(暂存区):
然后进行提交:git commit -m
后面的内容不要随便乱写,应说明提交内容。
这个提交是把修改的内容提交到本地仓库,就是本地.git
。此时出现两个错误:
这个报错信息提示我们要输入自己的邮箱号和名称:
修改成功之后重新进行上述操作:
本地仓库提交成功。
最后再提交到远程仓库,这个提交就是把.git
里面不一样的内容提交到远端仓库里面:
如上图就是成功提交。
我们可以通过git log
指令查看日志信息:
此时在Gitee网页端也能看到成功提交:
当我们想删除git中的proc.c文件时:
当我们想看看本地和远端之间的同步状态时可以使用git status
指令:
此时在远端仓库中文件还没有删除,要是想删除可以再次进行git三板斧:
git三板斧:
git add
--> git commit -m "说明"
--> git push
。
Gitee网页中没有proc.c文件,删除成功:
push时可以设置免密码,暂不建议免密码(免密提交)。
怎么删除本地仓库呢?
当.git
被删除后,这些文件就是Linux普通文件。
远程仓库需要在网页删除。