【Linux】Linux工具篇(yum、vim、gcc/g++、gdb、Makefile、git)


🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。
🚁 个人主页:不 良
🔥 系列专栏:🛹Linux   🛸C++
📕 学习格言:博观而约取,厚积而薄发
🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与诸君一同成长! 🌹


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指令查看是否能够运行,运行情况如下图。

image-20230228112053662

卸载指令——yum -y remove 软件包名称/yum remove -y 软件包名称

当我们不再使用该软件时,可以在root用户下通过指令yum -y remove 软件包名称进行卸载,普通用户需要使用sudo yum -y remove 软件包名称,如下图我们使用yum -y remove sl.x86_64卸载sl

image-20230228113002864

注意事项:

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:可选择本地机器上的文件上传到云服务器。

image-20230720093221162

指令sz + 文件名:可以选择云服务器上的文件下载到本地机器的指定文件夹中。

image-20230720093550940

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的文件,这是系统中公共的配置文件,对所有用户都有效。

image-20230720103922431

在每个用户的主目录/home/x下,都可以自己建立私有的配置文件,命名为.vimrc,这是该用户私有的配置文件,仅对该用户有效.一个用户一个vim配置,我们所做的配置不会影响其他人。

先创建一个文件:.vimrc,创建的配置文件都在这个文件中,配置即刻生效,如我们自己创建的配置文件中设置行号:

image-20230720105222264

不想使用的时候也可以通过双引号注释掉:

image-20230720111211672

b.自动配置(推荐)

我们这里推荐的方法就是直接执行以下指令(想在哪个用户下让vim配置生效,就在哪个用户下执行该指令,不推荐直接在root下执行):

curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh

在普通用户下安装,要按照提示输入root密码:

image-20230720111815148

在root用户下安装不需要输入密码,直接安装完成:安装成功之后需要按照命令提示操作,才能成功使用配置文件,需要退出用户登录或者输入source ~/.bashrc 命令。

image-20230720111900627

我们选择输入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可执行文件:

image-20230721091619176

可以通过gcc -o设定要生成的目标文件的名称,-o选项后面跟的一定是要生成文件的名称。上面的test.c文件我们想生成test可执行文件可以写成gcc -o test test.c或者gcc test.c -o test。比较推荐的是gcc test.c -o test

image-20230721092159938

gcc/g++过程分析

程序的翻译主要分为编译和链接,编译又可以分为预处理、编译、汇编

常用选项:
-E:从当前文件(.c文件开始)开始,进行程序的翻译,预处理做完就停止,预处理之后的文件习惯称为.i文件。
-S:从当前文件开始(可以从.c文件开始翻译,也可以从.i文件开始翻译),进行程序的翻译,当编译完成就停下来,编译后的文件通常以.s作为后缀,通常.s作为汇编文件的后缀
-c:从当前文件开始,进行程序的翻译,做完汇编就停止,生成的文件我们一般加后缀.o.o对等于windows中的.obj

预处理

  • 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
  • 预处理指令是以#号开头的代码行。
  • 选项-E,该选项的作用是让gcc在预处理结束后停止编译过程。
  • 选项-o是指目标文件,.i文件为已经预处理过的C原始程序
  • 举例cc

-E:从当前文件(.c文件开始)开始,进行程序的翻译,预处理做完就停止,预处理之后的文件习惯称为.i文件。

image-20230721093712079

如上图所示,当我们直接使用gcc -E 目标文件(这里我们测试用例使用的是test.c文件),会将执行结果直接打印在屏幕上,所以我们可以使用-o选项指定文件名称,假设我们要生成的文件名称是test.i文件:

image-20230721100601909

然后我们再对比一下:

image-20230721094537039

test.i就是预处理之后形成的临时文件,我们可以在test.i文件中可以看到头文件展开和宏替换,.i文件还是C语言。

编译

  • 在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后gcc把代码翻译成汇编语言。
  • 用户可以使用-S选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
  • 举例gcc -S test.i -o test.s

-S:从当前文件开始(可以从.c文件开始翻译,也可以从.i文件开始翻译),进行程序的翻译,当编译完成就停下来,编译后的文件通常以.s作为后缀,通常.s作为汇编文件的后缀。

image-20230721095040591

打开之后就是汇编语言:

image-20230721094951549

汇编

  • 汇编阶段是把编译阶段生成的.s文件转成目标文件.o
  • 使用选项-c可以看到汇编代码转化为.o的二进制目标代码
  • 举例:gcc –c test.s –o test.o

-c:从当前文件开始,进行程序的翻译,做完汇编就停止,生成的文件我们一般加后缀.o.o对等于windows中的.obj

image-20230721095613486

打开文件之后就是:

image-20230721095653199

不能执行该文件,即便添加权限也不能执行:

image-20230721095816948

说明.o和.obj文化都是不可以执行的。

链接

  • 在成功编译之后,就进入了链接阶段

  • 举例:gcc test.o -o test

image-20230721101526610

链接后生成的也是二进制文件。

动静态库

我们为什么能够在Linux下进行C、C++代码的编写呢?

Linux系统默认已经携带了语言级别的头文件和文件对应的库。

在Linux中库存放在哪里呢?存放在 /usr/include中:

image-20230721102423961

命令:ldd + 可执行程序文件名可以查找链接库的的位置:

image-20230721103734482

去掉前缀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指令后面跟上文件名,根据说明判断是否是动态链接,使用的是共享库。

image-20230721110637376

如果进行静态链接呢?在gcc进行编译时在后面加上-static选项,一般的云服务器默认都是只有动态库,如果在进行C语言和C++静态链接时可能会出现如下报错:

image-20230721111305637

此时可以通过命令yum install -y glibc-static安装C静态库,也可以通过yum install glibc-static libstdc++-static -y或者yum -y install glibc-static libstdc++-static同时安装C和C++的静态库:

image-20230721111534315

此时再查看文件类型时就会发现显示静态链接:

image-20230721111644868

我们可以观察一下两种不同链接方式生成的文件大小:

image-20230721111903812

充分证明了动态链接比静态链接更加节省空间。

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下通过下面的代码来更加详细的认识这些操作:

image-20230721114628438

当我们使用gcc test.c -o test编译运行的时候会出现如下报错:

image-20230721114714558

这是因为在for循环里初始化,是C99之后才能支持的,所以我们要在指令的后面加上 -std=c99或者-std=gnu99才可以:

image-20230721114955636

当我们想使用gdb调试的时候怎么调试呢?

当我们直接使用gdb加上可执行程序名时会出现如下报错信息:

image-20230721115248175

这是因为Linux下默认生成的是release版本的,而release不能用来调试,要在debug版本下进行调试,我们可以使用quit或q指令离开上述调试界面,在编译程序的时候添加-g选项可以使其为debug模式,-g:让gcc、g++以debug方式调试:

image-20230721115814103

为什么debug能调试,release不能调试?因为release是客户使用的,不加调试信息,体积相对较小。

读取可执行程序的二进制构成用readelf -S指令,Linux形成的可执行程序遵守的二进制规则是elf格式。

image-20230721120230178

搜索调试信息:

image-20230721120326976

gdb调试test,(gdb)后可以直接输入指令:

l 0或者l 1 (这里的l也可以替换成L)可以从第0行或者第1行开始查看代码信息,随后直接按enter就可以往下查看。l这个命令是list的简写:

image-20230721120829414

输入指令r进行调试,此时还没有打断点,直接执行完毕,正常执行正常退出:

image-20230721121057955

指令b 行号,设置断点,b后面跟的是行号:

image-20230721121327042

查看断点指令:info b,其中Num表示的是断点编号:

image-20230721121424203

再次运行r指令,在断点处停止,方便进行单步调试:

image-20230721121603157

再次查看断点info b,提示当前断点已经被命中一次:

image-20230721121651736

删除断点d 断点编号,d后面跟断点编号,删除之后输入info b查看发现当前无断点:

image-20230721121805954

输入r, 会提示是否从开始处运行,选择n,即继续向下调试;选择y就是从头开始:

image-20230723090538912

再次创建断点并且运行:编号是2,没有退出gdb,num编号依次递增:

image-20230723090900470

使能:不删除断点,让断点失去作用。在VS中右击断点可以看到关闭(实心变空心),输入disable breakpoint 断点编号或者disable 断点编号设置空断点,输入enable 断点编号使断点恢复作用:

image-20230723091823557

打断点我们也可以使用b + 函数名(文件名:函数名)或者b 文件名:行数

image-20230723092346888

在VS下:

逐过程(F10):以函数为单位不进入函数,跳过函数。

逐语句(F11):有函数进入函数。

gdb下类似于逐过程:用指令n(next也可以);逐语句:s(step也可以)指令进入函数。gdb会记住上一次的指令,所以我们可以直接按回车执行上一次输入的指令:

image-20230723092908847

监视可以用p 变量指令:

image-20230723093004682

想要一直看到变量变化,可以用display 变量指令:常显示(内置类型,结构体等自定义类型,stl等);

取消常显示,undisplay + 前面显示的编号才能够取消,如果加undisplay sum 不能取消:

image-20230723093437049

执行到把循环跑完,可以直接用until + 预期行数。下图中10显示的是预期要到的行数(在函数内,进行指定位置的跳转,执行完区间代码):

image-20230723093641949

当函数嵌套调用时可以查看压栈的过程,使用bt指令,最下面的就是最先执行的:

image-20230723093732074

finish指令:进入一个函数,只执行完该函数就停下(进入函数后):

image-20230723093939514

从一个断点到另一个断点,使用c(continue)指令,下图中是在第15行和第17行打断(从一个断点运行至下一个断点):

image-20230723094153899

set var 指令 :设置变量为某个值,下图中为设置变量i等于20:

image-20230723094605981

调试器:核心工作是为了定位问题。所有查看内容的指令,并不影响实际调试指令。

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指令生成可执行程序:

image-20230723100112314

但是我们可以直接使用Makefile文件,先创建一个Makefile文件,在里面编辑如下,test依赖于test.c,依赖方法为gcc test.c -o test

image-20230723100441870

第一行中,我们要用test.c形成test,通常我们把这组关系叫做依赖关系。

第二行我们叫做依赖方法。makefile是一个围绕依赖关系和依赖方法构建的一个自动化编译的工具,完成一件事情必须有正确的依赖关系和依赖方法。

make命令使其能够运行makefile文件中的内容:

image-20230723100650518

可以通过rm指令删除test可执行文件,也可以通过在Makefile文件中进行语句的定义之后调用命令进行清理:

image-20230723101019041

执行make clean指令:

image-20230723100940187

下图中按照编译的顺序进行操作,第一行中由test.o文件形成test文件,但是因为没有test.o文件,所以向下看……,这里就好像是栈,上面的依赖关系先入栈,然后再慢慢出栈。

Makefile文件中显示的是下面这样,但是在make执行时是先执行最下面的。

image-20230723102609215

通常不用这个方法写。

Makefile中的简写方式:

  • $@:表示依赖关系中的目标文件(冒号左侧)。
  • $^:表示依赖关系中的依赖文件列表(冒号右侧的所有文件)。
  • $<:表示依赖关系中的第一个依赖文件(冒号右侧第一个)。

image-20230723104109407

**依赖关系中目标文件对应的依赖文件列表可以是空。:前是目标文件,:后面的是目标文件列表。 **

清理:

image-20230723104547463

为什么make 后面要加上clean,而执行test时不需要呢?因为Makefile默认执行第一组依赖关系和依赖方法。我们也可以在执行make的时候在后面加上test,当我们把clean放到第一组的位置上,默认执行的就是clean。

make就是给Makefile制作的一个命令。

image-20230723105342852

上图意思是test文件已经是最新的了,不需要进行编译了。这也说明了test文件不是总是被执行的。

关键字:.PHONY:总是被执行的,一般用.PHONY修饰的符号称为伪目标,特征就是总是被执行的。 一般将clean的目标文件设置为伪目标。

我们通过给第一组依赖关系加上.PHONY来验证:

image-20230723105924256

不建议给目标文件加关键字.PHONY

上面执行时为什么make会知道这是最新的?

通过对比源代码和可执行程序的时间:

image-20230723110333837

Modify时间:可以通过touch源文件的方式在不更改源代码的情况下改变Modify时间:

image-20230723110721482

sudo提升权限

当我们使用sudo命令提升指令权限时,输入密码后提示:当前的用户不在系统的信任列表里:

image-20230723111118809

要是想使用sudo命令,首先要将用户添加到信任名单,信任名单在etc下的sudoers中,权限限制,需要root用户才能添加:

image-20230723111411853

在root用户下打开,root用户不受权限约束:

image-20230723111507355

上面的内容不管,我们直接找到上图所示的地方,然后yy复制,p粘贴,将名字修改为想要提升权限的用户名:

image-20230723111708677

但是在最下面还是会有下列提示信息:此时我们在w后面加上!就可以保存。此时就将用户添加信任列表里:

image-20230723112005201

此时再执行sudo指令就可以提升权限了,当用户登录的时候不能删除该用户。

Linux小程序——进度条

缓冲区的概念

我们先在Linux上执行下面的代码:

image-20230723112600966

执行结果:

7-23-1

当我们将代码修改为下面这样:

image-20230723113253782

执行结果为:

GIF 2023-7-23-2

两份代码的区别就是在printf打印时\n的区别,打印结果不相同证明了缓冲区的概念。

我们需要知道显示器对应的是行刷新,只有在缓冲区遇到\n或是缓冲区被写满,或者程序结束时缓冲区内容才会被打印出来,而在第二份代码当中并没有\n,所以字符串Hello demo先被写到缓冲区,休眠3秒之后,直到程序运行结束才将Hello demo打印到显示器当中。

那如果不使用\n进行换行怎么刷新缓冲区?可以使用fflush函数(头文件是stdio.h),该函数可以刷新缓冲区

image-20230723120424993

运行结果:

GIF 2023-7-23 12-05-05

\r和\n

\r: 回车,使光标回到本行行首。
\n: 换行,使光标下移一格。

观察下面代码:

image-20230723115526516

运行结果:

GIF 2023-7-23 11-56-23

当我们将上面的代码修改为下面的代码时就会被覆盖,原因就是\r把光标放在最开始,把打印出的内容给覆盖了:

image-20230723115849107

执行结果:

GIF 2023-7-23 11-58-17

\r不会刷新缓冲区。

倒计时小程序

我们可以利用\r的特性写一个倒计时小程序:

image-20230723120851816

利用\r的特点让每次输出的内容都从行首开始打印,运行结果:

GIF 2023-7-23 12-10-00

进度条小程序

进度条小程序代码:

image-20230723122921638

当想在进度条后面提示%多少时候,可以加如下代码,%符号在输出的时候可以用%%符号来表示。

运行结果:

GIF 2023-7-23 12-21-21

C语言也可以输出彩色:

image-20230723123105161

也可以将代码修改一下,给进度条加上颜色:

image-20230723124430769

打印结果:

GIF 2023-7-23 12-43-45

git命令行的使用

git是开源、去中心化、分布式的;git能够进行版本管理:在更新的同时,保存之前的版本,就是版本管理(版本号,可以根据标签分组)。

git --version命令,用来查看当前git版本。

image-20230723151356475

如果没有安装,可以使用yum install -y git进行安装,要注意需要在root用户下进行安装。

我们在Gitee官网建好仓库:

image-20230723151628180

创建成功之后,在管理最下面开源(空仓库不允许开源),还可以添加开发人员。

在Linux上使用git

我们在一个新建的测试目录下进行测试:

image-20230723151841571

先复制链接,然后git clone + 链接,把远端仓库的所有内容克隆过来,因为现在是私有仓库,需要输入用户名和密码,开源仓库可以直接拷贝。

image-20230814212745388

image-20230723152710632

把远端仓库克隆下来之后,cd进入仓库(如果此时不小心把仓库删掉了,再克隆就可以了,删本地不影响远端):

image-20230723152808533

查看REMADE.md:

image-20230723152835403

什么是仓库?就是.git目录,.git就是仓库,里面包含各种各样的文件,object下有版本号:

要注意不能修改.git名字。

将目标文件拷贝到当前git目录下:

image-20230723153441462

当前只是把文件拷贝到了本地的目录当中,并没有把文件添加到仓库中。

.就是把当前目录下所有没被添加的文件添加到仓库中(暂存区):

image-20230723153617926

然后进行提交:git commit -m后面的内容不要随便乱写,应说明提交内容。

这个提交是把修改的内容提交到本地仓库,就是本地.git。此时出现两个错误:

这个报错信息提示我们要输入自己的邮箱号和名称:

image-20230723154019123

修改成功之后重新进行上述操作:

image-20230723154255405

本地仓库提交成功。

最后再提交到远程仓库,这个提交就是把.git里面不一样的内容提交到远端仓库里面:

image-20230723154511300

如上图就是成功提交。

我们可以通过git log指令查看日志信息:

此时在Gitee网页端也能看到成功提交:

image-20230723154814097

当我们想删除git中的proc.c文件时:

image-20230723155021133

当我们想看看本地和远端之间的同步状态时可以使用git status指令:

image-20230723161452606

此时在远端仓库中文件还没有删除,要是想删除可以再次进行git三板斧:

git三板斧:

git add --> git commit -m "说明" --> git push

image-20230723161555107

Gitee网页中没有proc.c文件,删除成功:

image-20230723161329997

push时可以设置免密码,暂不建议免密码(免密提交)。

怎么删除本地仓库呢?

image-20230723161832664

.git被删除后,这些文件就是Linux普通文件。

远程仓库需要在网页删除。

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不 良

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值