[Linux]详解环境基础开发工具的使用

[Linux]环境基础开发工具的使用

0. 前言

要在Linux操作系统中开发,要学会使用Linux操作系统下的环境基础开发工具。

1. Linux 软件包管理器 yum

yum介绍

yum工具是Linux操作系统(centos)下的软件商店。

image-20230716195858903

  • yum是直接配置在Linux操作系统。
  • yum能够自动从远端服务器上找到对应的软件并下载到本地。
  • Linux操作系统作为开源系统,有着自己的社区,社区中有全世界各地的程序员在维护和改进Linux操作系统的代码。有很多的企业和个人在使用Linux操作系统开发,因此他们的开发依赖于Linux操作系统,会给Linux社区捐赠钱财、服务器以便于Linux操作系统的社区的工作,因此Linux也就有能力设置服务器提供给Linux操作系统的用户使用yum来下载软件。

yum的使用

查看要下载的软件:

yum list | grep 软件名
  • yum能安装的软件特别多,直接使用yum list命令会显示大量的软件信息,因此使用管道和grep指令对要找的软件进行过滤。

查看sl软件的信息(下图为查询出来的部分信息):

image-20230716202336383

  • 第一列信息为软件名。
  • 第二列信息为版本号。(el就是centos)
  • 第三列信息为软件来源。

下载并安装软件:

sudo yum -y install 软件名
  • sudo是使用普通用户然后以超级用户的身份执行命令,只有超级用户可以安装软件。
  • sudo需要配置后普通用户才能使用。
  • -y 选项是为了在卸载过程中不用确认安装。
  • 软件安装好后,所有使用这个该系统的用户都可以使用。

使用超级用户安装sl软件:

image-20230716204114911

卸载软件:

sudo yum -y remove 软件名
  • sudo是使用普通用户然后以超级用户的身份执行命令,只有超级用户可以卸载软件。
  • sudo需要配置后普通用户才能使用。
  • -y 选项是为了在卸载过程中不用确认卸载。

尝试删除sl软件:

image-20230716202907720

由于是普通用户,删除失败,需要使用超级用户的身份来卸载。

使用超级用户卸载该软件:

image-20230716203437590

由于没有使用-y选项,需要输入y确认卸载该软件。

image-20230716203408073

卸载成功。

yum源

yum作为软件商店必须知道软件的下载地址,这些下载地址一般被存储在配置文件中,这些配置文件就成为yum源。

  • yum源存储在/etc/yum.repos.d/路径下。
  • 可以修改yum源内的链接来更新或修改yum源。
  • 搭载Linux操作系统的云服务器的yum源是配置好的,一般不需要更新。

进入yum源所在的目录下查看:

image-20230716205837273

查看yum源:

image-20230716210116670

image-20230716210134794

yum源的更新:

  1. 备份老的yum源(使用mv指令备份)。
  2. wget获取新的yum源配置文件(可以通过网络搜素得到)。
  3. mv 重命名为老的yum源的名字。
  4. yum clean all && yum makecache。

关于软件

  • 软件的稳定性要比功能的多样性更重要。
  • 新版本的软件功能虽然功能很多,但是会有很多没有人发现的问题,由于是新的问题,一般很难短时间解决。
  • 旧版本的软件功能虽然较少,也有一定的问题,但是由于长时间的使用,存在的问题一般都有相应的解决方案。
  • 软件分为官方的软件和扩展软件。
  • 扩展软件一般都是版本比较新的或者一些比较新颖的软件。
  • 官方软件一般会将经过长期使用中认为可靠的扩展软件纳入。
  • 如果要安装的软件找不到,可能是在扩展软件源可以使用sudo yum install -y 软件名 -release来找到匹配的yum源,然后再进行安装。

2. Linux编辑器-vim

vim介绍

vim是Linux操作系统下内置的多模式编辑器。

  • vim是只能用于编辑文本的编辑器。
  • vim有5种基本模式:命令模式、插入模式、底行模式、替换模式、视图模式。
  • 直接在Linux下输入vim指令可以查看vim是否存在。

在Linux下输入vim:

image-20230716212910687

输入shift+: 然后输入q退出vim。

vim基本模式

image-20230802152332454

命令模式

打开vim时所处的模式就是命令模式,命令模式下是无法输入的。

  • 无论要切换到什么模式,都要从命令模式才能切换。
  • 无论在什么模式按下esc(可以多次按下),就能退回到命令模式。

用vim打开一个空文件,不进行任何操作,所处的是命令模式:

image-20230716213605188

插入模式

插入模式下可以进行进行文本编辑。

  • 在命令模式下输入(i/a/o)即可进入插入模式。

image-20230728183931856

底行模式

底行模式用于对文件中的指定内容执行保存、查找或替换等操作。

  • 在命令模式下输入shift+:即可进入插入模式。
  • 底行模式下输入q直接退出文件,不保存修改。
  • 底行模式下输入w会保存修改,不退出文件。
  • 底行模式下输入wq会保存修改并退出文件。
  • 底行模式下加上!会强制保存修改/退出文件。

image-20230728184517581

替换模式

替换模式下光标所在的字符会被替换成键盘输入的字符。

  • 在命令模式下输入shift+r即可进入插入模式。

image-20230728200306238

视图模式

视图模式针对的是块编辑,也就是选定某一块区域,连续的,快速的,高效的编辑文本。

  • 在命令模式下输入ctrl+v即可进入视图模式。

视图模式下批量注释:

  1. 进入视图模式

image-20230802145813576 2. 通过移动光标选定要注释的代码行:

image-20230802145924166

  1. 输入I(大写)和//:

image-20230802150059995

  1. 按下esc,批量注释完成:

image-20230802150131882

视图模式下批量取消注释:

  1. 进入视图模式

image-20230802150258530

  1. 移动光标选定要删除的注释:

image-20230802150340214

  1. 按下d即可取消注释:

image-20230802150408566

底行模式下的命令汇总

  • 调出和去掉行号: set nu / set nonu
  • 搜索指定内容: /要搜索的指定内容 – 查看下一个匹配,按下n,跳转到上一个匹配,按下shift+n
  • 不退出vim执行Linux命令: !执行的命令
  • 将指定字段替换成指定字段: %s/替换前的字段/替换后的字段/g
  • 同时打开其他文件: vs 要打开的文件 – 按住ctrl并且快速按两下w切换光标到其他文件

命令模式下的命令汇总

  • 复制光标所在的若干行代码: (n)yy – 如果使用yy指令复制代码前不输入数字,就代表复制当前行。

  • 在光标所在行的下一行粘贴先前复制的若干行代码: (n)p – 如果使用p指令粘贴代码前不输入数字,就代表在光标所在行的下一行粘贴一次。

  • 撤销上一步操作: u – 在底行模式下输入w保存的修改依旧可以撤销。

  • 撤销上一次撤销: ctrl+r – 在底行模式下输入w保存的修改依旧可以撤销。

  • 剪切当前行所在的若干行代码: (n)dd – 剪切的若干行代码可以使用(n)p命令进行粘贴, 只进行剪切不进行粘贴相当于删除操作。

  • 跳转到文本的最后一行: shift+g / G

  • 跳转到文本的第一行: gg

  • 跳转到文本的指定行行: n shift+g / n G

  • 跳转到当前行文本的开始: shift+$

  • 跳转到当前行文本的结尾: shift+^

  • 以单词为分割向前跳转一次: b

  • 以单词为分割向后跳转一次: w

  • 快速大小写切换: shift+~ – 按下一次后会将光标所在的字符进行大小写切换,并且光标会自动移动到下一个位置。

  • 将包括光标所在位置后的若干个字符替换成指定的字符: (n)r 要替换的指定字符

  • 将包括光标及光标往右的若干个字符删除: (n)x

  • 将包括光标及光标往左的若干个字符删除: (n)X

  • 光标的位置移动: h(左)j(下)k(上)l(右)

vim简单配置

  • 在目录/etc/下面,有个名为vimrc的文件,这是系统中公共的配置文件,对所有用户都有效。

  • 在每个用户的主目录/home/xxx下,都可以自己建立私有的配置文件,命名为“.vimrc”,这是该用户私有的配置文件,仅对该用户有效。

例如,普通用户在自己的主目录下建立了“.vimrc”文件后,在文件当中输入set nu指令并保存,下一次打开vim的时候就会自动显示行号。

vim的配置比较复杂,某些vim配置还需要使用插件,建议不要自己一个个去配置。比较简单的方法是直接执行以下指令(想在哪个用户下让vim配置生效,就在哪个用户下执行该指令,不推荐直接在root下执行):
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh

然后按照提示输入root密码:

然后等待安装配置,最后手动执行source ~/.bashrc即可。

image-20230728204036234

配置完成后,自动补全、行号显示以及自动缩进等功能就有了。

3. Linux编译器gcc/g++

gcc/g++分别是用于编译C语言和C++的编译器,gcc和g++的使用方式(指令)相同。

程序的完整编译

gcc [-o 要生成的文件名] 要编译的文件

说明: gcc 文件名就可以完成文件的编译在当前目录下生成名为a.out可执行程序,加上-o可以指定生成的程序的文件名。

image-20230729154321844

程序的分布编译

程序编译的完整过程:

  1. 预处理
  2. 编译
  3. 汇编
  4. 链接

对文件进行预处理

gcc -E 要处理的文件名 [-o 要生成的文件名]

说明: 建议将生成的文件命名为.i后缀的文件。

对test.c文件进行预处理生成test.i文件:

image-20230729154739105

test.i是由test.c预处理所得的,因此会将test.c的头文件展开使得代码行数变多,并且还会进行宏替换和条件编译和去除注释,因此在test.i文件中看到不到宏定义、条件编译和注释,此时文件内容还是C语言。

对文件进行编译

gcc -S 要处理的文件名 [-o 要生成的文件名]

说明: 建议将生成的文件命名为.s后缀的文件,可以对预处理的结果文件进行操作,也可以对源文件进行操作。

对预处理得到test.i文件进行编译得到test.s文件:

image-20230729155519168

test.s是由test.i编译所得的,编译时会将C语言代码转化成汇编语言。

对文件进行汇编

gcc -c 要处理的文件名 [-o 要生成的文件名]

说明: 建议将生成的文件命名为.o后缀的文件,可以对预处理的结果文件、编译的结果文件进行操作,也可以对源文件进行操作。

对编译得到test.s文件进行汇编得到test.o文件:

image-20230729160202816

test.o是由test.s汇编所得的,汇编时会将编译所得文件转化成不可执行的二进制代码。

对文件进行链接

文件的链接没有特殊的命令选项,只使用程序的完整编译的指令,Linux系统内置了C语言的库,编译器会自动完成链接过程。

查看可执行程序连接时使用的库

ldd 可执行程序文件名

ldd查看可执行程序连接的库:

image-20230729160943100

动态库和静态库

编译器链接的库分为静态库和动态库

静态库: 链接静态库时,会将静态库中对应的代码拷贝至可执行程序中,因此链接静态库的程序占用的空间较大,但是如果静态库消失了不影响程序的执行,静态库一般以.a为后缀。

动态库: 链接动态库时,会将动态库中对应的代码的地址拷贝至可执行程序中,因此动态链接的程序占用内存较小,但是如果静态库消失了程序就无法正常执行了,动态库一般以.so为后缀。

静态库:

优点:不依赖库,可以独立执行,程序的可移植性较高。

缺点:占用较大空间。

动态库:

优点:占用较小的空间,多个程序可以共同使用动态共享库的代码。

缺点:依赖库,不可以独立执行,程序的可移植性较低。

通过file指令查看程序的链接情况:

image-20230729165622754

可以看到mytest可执行程序使用的是动态链接,使用的是共享库。

gcc [-o 要生成的文件名] 要编译的文件 -static

说明: 如果没有安装C语言静态库,可以执行yum install -y glibc-static来安装,同样的可以执行yum install -y libstdc++-static安装C++静态库。

在gcc编译是加上-static命令选项可以获得静态链接的程序:

image-20230729165909556

可以看到mytest-static使用的是静态链接,并且文件大小大于动态链接的mytest可执行程序。

4. Linux项目自动化构建工具-Makefile

Makefile文件能够实现自动化编译功能的工具。

说明: Makefile文件需要创建在要编译的源文件的目录下。

Makefile的组成

Makefile由依赖关系和依赖方法组成的自动化编译工具。

依赖关系

依赖关系是用于指明目标文件和源文件的关系说明。

依赖方法

依赖方法是用于指明通过源文件得到目标文件的执行方法。

在目录下创建一个test.c源文件和Makefile(makefile)文件:

image-20230729182028699

在Makefile文件中对于test.c文件建立如下依赖关系和依赖方法:

image-20230729183004157

写好Makefile文件后,输入make命令执行Makefile文件:

image-20230729182534882

执行make命令后,会自动在Makefile文件中查看依赖关系进行自动化编译,由于mytest依赖于test.o, test.o依赖于test.s, test.s依赖于test.i, test.i依赖于test.c的依赖关系,因此执行的依赖方法是和Makefile依赖关系的顺序相反的。

.PHONY关键字

.PHONY关键字是Makefile文件用于标识伪目标文件,使得依赖关系对应的依赖方法能够总是被完成。

对一个Makefile文件多次执行make命令:

image-20230729184414851

通常多次执行make命令时只有第一次执行会成功,后续执行时,会报文件已经是最新的的错误信息,此时只需要将要完成的依赖关系使用.PHONY关键字标识即可让该依赖关系对应的依赖方法总是被完成,修改Makefile为如下内容:

image-20230729184648767

make可以连续多次执行,不受限制:

image-20230729184743721

通常.PHONY关键字用于目标文件的清理:

image-20230729184943944

执行make clean指令,指定执行clean的依赖方法对应的依赖方法:

image-20230729185459003

说明:

  • 依赖关系的源文件可以为空。
  • 在执行make命令时只会完成Makefile文件中从上到下扫描到的第一个依赖关系对应的依赖方法。(如果第一个依赖关系中的源文件来自于其他依赖关系会将它们一并执行)
  • 执行make指令时可以指定要执行的依赖方法。

make指令识别不能多次执行的原理

make指令识别不能多次执行是通过对比源文件最后一次修改时间和可执行程序生成的时间,如下:

image-20230729191517204

  • 源文件最后一次修改时间 早于 可执行程序生成时间 – make指令不再重复执行
  • 源文件最后一次修改时间 晚于 可执行程序生成时间 – make指令可以执行

通过stat指令查看文件的创建和修改时间:

对已有文件touch可以修改文件的修改时间:

image-20230729194619872

all关键字

all 是一个常用的关键字,用于定义一个名为 “all” 的目标。all 目标通常被用作默认目标,也就是在执行 make命令时,如果没有指定目标,默认会执行 all 目标。

为了更好的说明all关键字的作用,准备如下源文件test1.c、test2.c内容如下:

image-20230802151058346

建立makefile文件,内容如下:

all:mytest1 mytest2
mytest1:test1.c
	gcc -o mytest1 test1.c
mytest2:test2.c
	gcc -o mytest2 test2.c

.PHONY:clean
clean:
	rm -f mytest1 mytest2

输入make指令:

image-20230802151312229

由于all目标的依赖关系需要mytest1、mytest2,因此make指令自动向下寻找mytest1、mytest2的依赖关系和依赖方法进行执行,完成多文件一次性自动化编译。

输入make clean一次性完成多个程序的清除:

image-20230802151516235

5. Linux调试器-gdb

gdb是Linux系统下的调试器。

  • gdb调试的程序只能是debug版本。
  • gcc/g++出来的二进制程序,默认是release模式 ,要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项。

为了方便进行调试,准备如下代码:

#include <stdio.h>

int AddToTop(int top)
{
    
    
  printf("enter the func\n");
  int sum = 0;
  for (int i=0; i <= top; i++)
  {
    
    
    sum += i;
  }
  printf("quit the func\n");
  return sum;
}

int main()
{
    
    
  int top = 100;
  printf("the sum is %d\n", AddToTop(top));
  return 0;
}

准备makefile文件,内容如下:

mytest:test.c
	gcc -o mytest test.c -g -std=c99
.PHONY:clean
clean:
	rm -f mytest

说明:

  • 由于代码中使用了循环内定义变量,因此需要在编译时注明使用C99标准,避免编译失败。
  • 使用-g选项使得形成的二进制程序为debug版本。

准备好代码和makefile文件后进行编译形成可执行程序,为了确保可执行程序有调试信息,使用readelf - S mytest | grep debug查看:

image-20230802121818005

使用gdb启动对程序的调试:

image-20230802121955983

查看代码指令: l(list) + 数字 --从对应行开始显示代码。

从第一行开始显示代码:

image-20230802122552997

由于gdb会记录上一次的命令,因此输入回车即可继续显示下面的代码:

image-20230802122627028

打断点指令: b(breakpoint) + 数字/源文件:函数名 – 在代码的对应行打上断点。

在代码的18行打上断点:

image-20230802122830696

查看已有断点指令: info b(breakpoint)。

image-20230802122957922

部分信息说明:

  • Num – 断点编号。
  • What – 说明断点所在的源文件和所在的位置。

运行程序指令: r(run) – 如果有断点会运行到断点处停止,没有断点会运行到程序结束位置。

运行程序至断点处:

再查看断点信息,断点信息中记录了断点被命中一次:

image-20230802123551646

删除断点指令: d(delete) + 断点编号 – 删除对应断点编号的断点。

删除断点编号为1的断点:

image-20230802123840597

关闭断点指令: disable breakpoint 断点编号。

关闭断点编号为2的断点:

image-20230802124410058

说明: Enb信息列为n表示断点关闭,y为断点打开。

启动断点指令: enable breakpoint 断点编号。

启动断点编号为2的断点:

image-20230802124551179

逐过程执行代码指令: n(next)。

run执行程序后进行输入next逐过程执行代码:

image-20230802135656755

逐语句执行代码指令: s(step)。

run执行程序后进行输入s逐语句执行代码:

image-20230802135754713

通过bt指令可以查看函数调用结构:

image-20230802140115556

监视变量指令: p/display 变量名 – p为显示一次,dispaly为常显示,undisplay+编号取消常显示。

监视变量的值:

image-20230802140502040

取消编号为1的常显示:

image-20230802140838468

跳转代码指令: until + 数字 – 在函数体,将代码跳转至对应行。

在AddToTop函数中跳转至第10行:

image-20230802141517544

完成当前函数的执行指令: finish – 直接完成当前函数的执行。

直接完成AddToTop函数的执行,并且得到返回值:

image-20230802141731958

跳转到下一个断点的位置指令: c(continue)。

image-20230802142551214

退出gdb指令: quit。

猜你喜欢

转载自blog.csdn.net/csdn_myhome/article/details/132063646