【Liunx系统编程】开发工具

本文详细介绍了Linux开发环境中的关键工具,包括vim文本编辑器的使用、gcc/g++编译器操作、gdb调试器的命令集以及makefile的原理和应用。内容涵盖了基本操作、配置设置和项目自动化构建的关键点。
摘要由CSDN通过智能技术生成

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

我们编写C/C++程序使用vs,编译,运行,调试都是一体的,而在Liunx都分开的。

1.Linux编辑器-vim使用

vi/vim 是 Linux 系统内置的不可或缺的文本编辑命令,vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window、 mac os、windows。我们主要学vim。

1.1vim的基本概念

这里主要讲解vim的三种模式(其实有好多模式,目前掌握这3种即可),分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:

正常/普通/命令模式(Normal mode)
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode

插入模式(Insert mode)
只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。

末行模式(last line mode)
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+; 即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入:

help vim-modes

1.2vim的基本操作

进入vim,在系统提示符号输入vim及文件名称后,就进入vim全屏幕编辑画面:
在这里插入图片描述
不过有一点要特别注意,就是你进入vim之后,是处于[正常模式],你要切换到[插入模式]才能够输入文字

[正常模式]切换至[插入模式]
输入a
输入i
输入o

[插入模式]切换至[正常模式]
目前处于[插入模式],就只能一直输入文字,如果发现输错了字,想用光标键往回移动,将该字删除,可以先按一下「ESC」键转到[正常模式]再删除文字。当然,也可以直接删除。

[正常模式]切换至[末行模式]
「shift + ;」, 其实就是输入「:」
退出vim及保存文件,在[正常模式]下,按一下「:」冒号键进入「Last line mode」,例如:
: w (保存当前文件)
: wq (输入「wq」,存盘并退出vim)
: q! (输入q!,不存盘强制退出vim)

在这里插入图片描述

1.3命令模式命令集

1.3.1光标定位

光标移到改行最右边

shift + 4 -----> $

光标移到改行最左边

shift + 6 -----> ^

光标到结尾

shift + g -----> G

光标到开头

gg

跳转光标到指定行,n代表的是行号

n+shift+g

1.3.2光标移动

h

j

k

l

向后按照单词移动

w

支持 nw

向前按照单词移动

b

支持 nb

1.3.3文本复制

执行的是光标所在行位置

复制

yy

默认复制一行

nyy

支持光标所在行,进行多行复制 n是行数

粘贴

p

光标在哪里,就向哪里粘贴。默认一次

np

支持对内容,进行多行粘贴

撤销

u

删除

dd

删除光标所在行

ndd

支持光标所在行,进行多行删除

剪切

dd+p

在光标所在行进行剪切

ndd+p

支持多行剪切

取消u操作

ctrl+r

1.3.4文本操作

文本行大小写转换

shift+~

文本行批量化替换(当前行文本写错,不想删除,直接shift+r,换一行内容)

shift+r

shift+r其实由命令模式切换到替换模式

替换光标所在行的一个字符

r

替换光标所在行n个字符,只能换成一样的

nr

替换光标所在行的字符,随意替换

R

行内删除,向后删除一个字符

x

向后删除n个字符,包括光标所在位这个位置

nx

向前删除一个字符

shift+x ------>X

向前删除n个字符,不包括光标所在位这个位置

n+shift+x

剪切操作

nx+p

删除光标所在行的单词,并进入插入模式

cw

删除光标所在行n个单词,并进入插入模式

cnw

1.4插入模式命令集

命令模式切换到插入模式

i/a/o

1.5底行模式命令集

调出/取消行号

set nu/nonu

强制退出

q!

强制写入

w!

强制写入并退出

wq!

分屏

vs 文件名

在这里插入图片描述

无论分多少屏幕,光标只有一个!!光标的意义:选中当前行(编辑的位置)或者屏幕。

光标跨屏幕

ctrl+ww

有了这个指令,就可以尝试在不同文件里进行其他操作了

不退出vim,执行Liunx命令

!+指令

在这里插入图片描述
按q退出

替换

%s/前/后/g

把文件里属于前的内容全部用后的内容替换

在这里插入图片描述在这里插入图片描述

2.vim配置

1.vim配置是一人一份的,一个用户配置的是自己的,不影响别人。
2.每个人虽然用的都是同一个vim程序,但是大家用的是不同的vim配置,这是因为每个用户,在自己家目录下配置,这样就是独属于自己的配置了。

vim的基本配置
在自己家目录下创建一个.vimrc文件,在里面配置
在这里插入图片描述
在这里插入图片描述
打开文件,会自动显示行号
在这里插入图片描述
感兴趣可以到网上搜索一下vim配置,配置属于你自己的那一份。

这里有一份别人配置好的,分享给大家。
vim配置

往下翻,找到这个,复制这条命令,在自己家目录下执行这条命令
在这里插入图片描述
输入root密码,然后等待安装
在这里插入图片描述
在这里插入图片描述
这样就配置就完成了。自己上手看一下效果,
在这里插入图片描述
这里就是我们配置好的文件,不要删除,保留即可
在这里插入图片描述
这里配置Tab有一点点问题,打开.vimrc文件
在这里插入图片描述
找到这里把2,都修改成4,保存退出,这样完整的一份vim就好了。
在这里插入图片描述
在这里插入图片描述

3.sudo配置

1.先把自己切换成root
在这里插入图片描述
2.编辑sudoers文件
在这里插入图片描述
找到这里,复制粘贴一下,然后强制保存退出,
在这里插入图片描述
在sudo提权的时候,输入一下自己的密码就可以正常使用了。

4.Linux编辑器-gcc/g++使用

4.1背景知识

我们知道程序编辑完,ctrl+F5就会把编译和链接都完成了。但是编译到链接又分了几个步骤:
1.预处理(头文件展开,去注释,宏的替换,条件编译)
2.编译(把c语言变成汇编语言)
3.汇编(把汇编语言生成二进制指令)
4.链接(将目标文件和链接库进行链接生成可执行文件)

4.2gcc如何操作

格式 gcc [选项] 要编译的文件 [选项] [目标文件]

以下面这段代码为例

在这里插入图片描述

1.直接完成编译和链接过程生成可执行程序

gcc test.c

在这里插入图片描述
a.out就是可执行程序

./a.out

执行可执行程序
在这里插入图片描述

2.依次处理编译和链接过程

预处理
预处理功能主要包括头文件展开,去注释,宏的替换,条件编译等。
预处理指令是以#号开头的代码行。
实例:

gcc –E test.c –o test.i

选项“-E”,该选项的作用是从现在开始,进行程序的翻译,当预处理完成之后,就停下来
选项“-o”是指形成的临时文件,“.i”文件为已经过预处理的C原始程序

编译
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
实例:

gcc -S test.i -o test.s

选项“-S”,该选项的作用是从现在开始,进行程序的翻译,做完编译工作,变成汇编语言后就停下来。

汇编
汇编阶段是把编译阶段生成的“.s”文件转成目标文件(该目标文件不是可执行文件,只是二进制目标文件)
实例:

gcc -c test.s -o test.o

选项“-c”,该选项的作用是从现在开始,进行程序的翻译,做完汇编工作,编程二进制目标文件就停下来

下面指令,可以查看二进制指令

od test.o

做完上面的工作,一定不能忘记链接的过程,因为上面的只是在编译你的代码,就比如说printf是一个库函数,我们直接就使用了,头文件展开只是告诉这个函数怎么用,有这个函数。并没有定义它,必须要去库里面找。

链接
把自己写的代码与C标准库的代码合起来形成可执行程序
实例:

gcc test.o -o mytest

指定可执行程序名称

gcc test.o 

形成可执行程序默认名称为a.out

如果想执行C++代码,把gcc换成g++

5.函数库

就如上面所说,printf我们并没有去定义实现它,头文件包含了对该函数的声明,而没有定义函数的实现,那么是在哪里实现printf函数的呢?

答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用

5.1函数库的分类

链接的本质:就是我们调用库函数的时候,和标准库如何关联的问题。

函数库分为动态库和静态库。
在这里插入图片描述
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。

动态库和静态库优缺点:
优点:
动态库:形成的可执行程序小,节省资源(内存,磁盘,网络)。
静态库:不受库升级或者被删除等影响。

缺点:
动态库:受到库升级或被删除等影响
静态库:形成可执行程序太大

gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证

file mytest

在这里插入图片描述

查看可执行程序依赖的动态库列表

ldd mytest

在这里插入图片描述

动态库
libxxx.so
lib前缀
.so后缀
去掉前缀和后缀,剩下的就是库名称

静态库
libxxx.a
lib前缀
.a后缀

Liunx下默认形成可执行程序使用“动态库”

动态

gcc test.c -o mytest

静态(需要指定)

gcc test.c -o mytest -static

注意

如果系统中只提供.so文件,只能用动态链接,或者只提供.a文件,即使不指定static也是静态链接。如果动静态库都有,默认使用动态库。

一般而言,系统会自动携带动态库的,这是因为系统的运行就需要动态库。静态库如果不存在需要自己手动安装。

安装C静态库

sudo yun install -y glibc-static

安装C++静态库

sudo yum install -y libstdc++-static

关于Liunx的动静态库的问题,在windows下原理是一样的。
默认形成可执行程序:动态链接

windows下动态库后缀.dll,静态库后缀.lib

注意:系统本身为了支持我们编程,除了提供标准库.h,还提供了标准库的实现.so/.a

6.Liunx调试器-gdb使用

Liunx和windows调试方式不一样,但调试思路是一样的。
Liunx是使用gdb命令行调试

6.1背景知识

1.程序的发布方式有两种,debug模式和release模式。
2.Linux gcc/g++出来的二进制程序,默认是release模式。gdb不能直接对release模式下发行的程序进行调试,需要改成debug模式下发行的程序。
3.生成debug模式下的程序,必须在源代码生成二进制程序的时候, 加上 -g 选项

总结:

gcc默认行为
1.默认动态链接
2.默认release模式

vim默认行为
1.默认打开就是命令模式

开始调试

gcc test.c -g -o mytest
gdb mytest

退出调试

q

6.2gdb命令集

下面命令都是简写,也可以使用完整的命令

显示代码
list

l

从0行开始显示代码

l 0

这里显示代码并不会完全显示出来,再按回车键继续显示

在n行设置断点
break

b n

查看断点

info b

删除断点
delete

d 编号

在这里插入图片描述

调试运行,跑到断点处
run

r

逐过程
next

n

逐语句
step

s

跳转到下一个断点处
contiue

c

查看函数调用堆栈

bt

执行当前函数返回,然后停下来等待命令

finish

在这里插入图片描述

查看变量/地址
p,只显示一次

p 变量/地址

常显示

display 变量/地址

取消常显示

undisplay 编号

跳转到指定行

until n

修改变量的值
i是变量

set var i=100

显示当前栈帧局部变量的值

info locals

禁用断点

disable breakpoint 编号

启用断点

enable 编号

7.Linux项目自动化构建工具-make/Makefile

7.1背景

1.会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
2.一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
3.makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
4.make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
5.make是一条命令makefile是一个文件,两个搭配使用,完成项目自动化构建。

7.2makefile原理

makefile存在的意义:是为了构建项目(做一件事情)。
构建项目需要:1.依赖关系 2.依赖方法

比如,要做一件事情,找你爸要钱。
a.表明依赖关系(我是你的儿子/女儿)
b.表面依赖方法(你得给我转钱)

7.3初步理解makefile的语法

在代码路径下创建一个makefile文件
在这里插入图片描述
在这里插入图片描述

第一行依赖关系,:左边目标文件/可执行程序:右边依赖文件列表
第二行依赖方法,必须以Tab键开头

依赖关系:目标文件/可执行程序与源文件互相依赖关系
依赖方法:根据依赖关系,从依赖文件列表生成目标文件/可执行程序

有了可执行程序,还需要一个删除可执行程序指令。

在这里插入图片描述
clean不需要依赖

.PHONY被该关键字修饰的对象是一个伪目标,该目标总是可以被执行

在这里插入图片描述

再看下面图片,对比一下两张图片
在这里插入图片描述

发现只能make一次,make clean可以执行多次,gcc是如何得知,我不需要编译了呢?

stat 文件名(查看文件属性)  

在这里插入图片描述

Access:文件被访问的时间
Modify:文件内容被修改的时间
Change:文件属性被修改的时间

在这里插入图片描述
在这里插入图片描述

修改文件内容的时候,发现文件属性也变了,这是为什么?
因为文件大小变量,属性也就变了。文件属性包括:文件名,类型,大小。。。

至于大家看到Access也变了,下面就解释。

在看下面一张图片
在这里插入图片描述

当我们读取内容的时候,发现有的时候Access时间不变,这是为什么呢?
首先回答,文件操作时,改文件内容多,还是访问多?
肯定时访问多。如果一访问就修改Access的时间,需要进行多次IO操作,其次没人会关心访问文件多少次。

因此,一段时间访问次数够了,Access才会变。

gcc是根据对比源文件和可执行程序的Modify时间的新旧来判断,来判断可执行程序是否重新编译。
源文件比可执行程序时间旧,就不用重新编译,如果新就重新编译。

因此凡是被.PHONY修饰的,不再根据对比modify时间新旧的策略,而是总是执行一次。

7.4两个问题

问:
为什么make,就可以执行makefile第一条规则,执行第二条规则必须make clean?
答:
make默认从上到下扫描文本,默认第一个被扫描的目标文件,可以省略名称。

问:
make为什么走完第一条规则就不往下走了?
答:
默认情况下makefile只形成一个目标文件,后续的依赖关系和依赖方法不再执行,默认从上到下扫描只执行第一个。默认不指定就执行第一个。

7.5makefile推导规则

mytest:test.c

其实mytest并不直接依赖test.c

真实情况是这样

mytest:test.o
	gcc test.o -o mytest
test.o:test.s
	gcc -c test.s -o test.o
test.s:test.i
	gcc -S test.i -o test.s
test.i:test.c
	gcc -E test.c -o test.i

mytest依赖test.o,test.o不存在因此不执行依赖方法,然后去找test.o。。。。最后test.i依赖test.c,test.c存在执行依赖方法,然后层层返依次执行。

但是不推荐这样写,直接mytest:test.c,下面跟着依赖方法就行了。

自此关于Liunx编辑器vim,编译器gcc/g++,调试器gdb,vim配置,sudo配置,以及简单了解Liunx项目自动化构建工具make/makefile到这里暂时告一段落。

觉得有帮助的,点赞,评论,收藏,谢谢!!!

在这里插入图片描述

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值