Linux基础开发工具的使用(apt、vim、gcc、g++、gdb、make、makefile)
Linux软件包管理器–apt
Linux安装软件的方式
在Linux下安装软件的方法有以下三种:
- 下载到程序的源代码,自己编译出可执行程序
- 获取deb安装包、然后使用dpkg命令安装。(不解决依赖关系)
- 通过apt进行安装软件。
小知识点: .rpm是Centos的安装包;.deb是Ubuntu安装包。
apt
apt是Linux中Ubuntu系统的一个前端软件包管理器,能够从指定的服务器中自动下载deb包并安装,并可以自动处理依赖关系。
如下图所示:
也就是说,apt就相当于是应用市场的名字,而我们通过应用市场下载软件,会去服务器上拉取相应的安装包下载到本地,然后在本地安装。
而我们下载东西是需要联网的,因此我们下载时需要联网。
判断是否联网可以使用ping指令,如果不断的进行打印,代表是在联网状态下的。
如下:
查找软件包
我们可以使用apt list指令,这个指令可以列出apt中的全部包。
apt list
但这个指令一般都会直接刷屏,因此,我们一般都是搭配着管道和搜索使用。
如下:
apt list | grep lrzsz
但,这样过于繁琐,在apt中,我们可以直接使用search指令进行搜索。
apt search lrzsz
安装软件
安装软件,需要sudo权限。
指令: sudo apt install 软件名
apt会自动找到需要下载的软件包,然后询问我们是否需要安装,按“y”确认安装,等到出现complete时,安装成功。
现在,我们就可以安装下lrzsz软件。
apt install lrzsz
本地环境和云服务器之间文件的互传
现在,我们说以下lrzsz的使用。
lrzsz可以完成云服务器和本地机器文件的互传。
指令: rz -E
这个指令可以选择从本地机器上传到云服务器的文件
指令: sz 文件名
这个指令可以从云服务器发送文件到本地机器的指定文件夹。
软件的卸载
卸载软件使用的指令如下:
sudo apt remove 软件名
vim
而我们在linux中编写代码的时候,肯定需要一个能够写代码的工具。
那么,这个工具就是vim。
这里,我们介绍下vim。
vim的基本概念
vim作为一个多模式的文本编辑器,可以解决我们编写代码的问题。
我们主要学习vim的三个模式:
1、命令模式
在命令模式下我们可以:
- 控制屏幕光标的移动
- 字符、字、行的删除,复制粘贴剪贴等操作。
2、插入模式
文字的输入
3、底行模式
在底行模式下,我们可以保存文件,也可以进行一系列的操作,譬如查找字符串。
在底行模式下,还可以执行Linux的指令。
在vim中,模式不仅有三个,而是有很多个,我们还可以在底行模式下输入vim help-mode查看当前vim的所有模式。
vim各模式的切换
首先,我们先学下怎么进入vim
vim 文件名
如果该文件存在,则使用vim进入,如果该文件不存在,则创建该文件并使用vim进入
进入vim时,默认是命令模式。
这时,我们按i,即可进入插入模式。
如果我们在插入模式中按Esc,即可再次进入到命令模式。
在命令模式中,按Shift+;,即可进入底行模式。
此时,我们如果想要回到命令模式,可以再按一次Esc。
命令模式指令
光标移动:
- h, j, k, l:这些是标准的光标移动命令,分别对应左、下、上、右移动一格。
- G:移动到文本的最后一行。
- $:移动到当前行的末尾。
- ^:移动到当前行的第一个非空字符位置。
- w:移动到下一个单词的开头。
- e:移动到下一个单词的结尾。
- b:移动到上一个单词的开头。
- nl:跳转到该行的指定位置(例如,5l表示跳到该行的第5个字符)。
- gg:移动到文档的开头。
- Shift+G:移动到文档的末尾。
- Ctrl+b:向后滚动一屏。
- Ctrl+f:向前滚动一屏。
- Ctrl+u:向后滚动半屏。
- Ctrl+d:向前滚动半屏。
删除: - x:删除光标所在位置的字符。
- nx:删除光标位置之后的指定个字符(例如,6x表示删除6个字符)。
- X:删除光标前一个字符。
- nX:删除光标前面的指定个字符(例如,20X表示删除光标前面的20个字符)。
- dd:删除光标所在行。
- ndd:删除光标所在行及其后的#行(例如,6dd表示删除光标所在行及之后的6行)。
复制: - yw:将光标所在位置到单词尾部的字符复制到缓冲区。
- nyw:复制#个单词到缓冲区(例如,3yw表示复制接下来的3个单词)。
- yy:复制光标所在行。
- nyy:复制从光标所在行往下的n行(例如,6yy表示复制从当前行开始的6行)。
- p:将缓冲区的内容粘贴到光标所在位置。
替换: - r:替换光标所在位置的字符。
- R:替换光标所在位置及其后的字符,直到按下 ESC 键。
撤销与恢复: - u:撤销上一个操作。可以多次按 u 来撤销多次操作。
- Ctrl+r:恢复上一个撤销的操作。
更改: - cw:更改光标所在位置到当前单词的结尾。
- cnw:更改光标所在位置到下一个n个单词的结尾(例如,c3w表示更改3个单词)。
跳转到指定行: - Ctrl+g:显示光标所在行的行号。
- nG:跳转到文档中的第n行(例如,15G表示跳到第15行)。
底行模式指令(重要)
行号设置:
- set nu:显示行号
- set nonu:取消行号
跳转:
- n:n代表一个数字,在冒号后输入一个数字,然后再按回车键即可跳转到该行了。
查找字符:
- /关键字:先按/,再输入想查找的字符,一直按n可以往后找到想要的字符。(从前向后)
- ?关键字:先按?,再输入想查找的字符,一直按n可以往前找到想要的字符。(从后向前)
保存退出: - w:保存
- q:退出(如果没有退出vim,则可以加一个!表示强制退出)
- wq:保存退出
分屏: - vs 文件名:多文件编辑
- Crtl+w+w:光标再多屏幕下进行切换
执行命令: - !+指令:在不退出vim的情况下,在指令前加上!就可以执行Linux的指令。
vim的配置方法
Vim 配置文件通常位于以下位置:
- 系统级配置文件:
/etc/vimrc
,适用于所有用户。 - 用户级配置文件:
~/.vimrc
,每个用户可以自定义该文件。
详细的vim配置,大家根据需求自己上网搜就好了哈
创建或编辑个人 .vimrc
- 切换到用户的主目录:
cd ~
.vimrc 文件(如果文件不存在,可以创建一个新的):
vim .vimrc
常用配置选项
在 .vimrc 中可以加入以下配置选项:
启用语法高亮:
syntax on
启用行号:
set nu
设置缩进为4
set shiftwidth=4
Liunx下C/C++编译器:gcc/g++
gcc和g++分别是C和C++的编译器。
gcc/g++的作用
C/C++程序在执行编译时有以下四个步骤:
- 预处理(头文件展开、去注释、宏替换、条件编译)
- 编译(C代码翻译为汇编代码)
- 汇编(汇编代码转化为二进制代码)
- 链接(将各个二进制代码进行链接)
下面,我们一边讲gcc,一边写这四个阶段。
gcc/g++的语法
语法: gcc/g++ 选项 文件
常用选项:
- -E 只进行预处理
- -S 只进行预处理和编译
- -c 进行预处理、编译、汇编
- -o 将处理结果输出到指定文件,后要跟文件名
- -static 对文件采用静态链接的方式
- -g 生成调试信息(debug版本)(若不带此选项,则默认生成release版本)
- -shared 尽量使用动态库
- -w 不生成任何警告信息
- -O0/-O1/-O2/-O3 编译器优化选项的四个级别,优化力度依次递增。
预处理
gcc -E test.c -o test.i
- 预处理功能包含头文件展开、去注释、宏替换、条件编译等。
- 预处理指令是以#开头的代码行
- -o选项是指目标文件,“.i”为结尾的文件为已经预处理过后的文件。
编译
gcc -S test.i -o test.s
- 编译阶段中,gcc/g++会检查代码是否规范,是否具有语法错误,以及确定代码的功能。在检查无误后,会将代码翻译为汇编语言。
- -o选项是指目标文件 “xxx.s”是翻译后的原始程序。
汇编
gcc -c test.s -o test.o
-汇编阶段是将-s文件转化为-o文件,即目标文件。
-o文件是二进制目标代码。
链接
gcc test.o -o test
- 链接的主要任务是将生成的各个.o文件进行链接,生成可执行文件。
- 若不带-o选项,则默认生成的可执行文件名为a.out
- 不带选项时,默认将预处理、编译、汇编、链接四个过程全做完。
动静态链接和动静态库
动静态链接
静态链接
在我们的实际开发中,不会将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽多个源⽂件之间不是独⽴的,⽽会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数,但,每个源⽂件又都是独⽴编译的,因此每个*.c⽂件会形成⼀个*.o⽂件,为了满⾜前⾯说的依赖关系,则需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。这个链接的过程就是静态链接。
很显然,静态链接的弊端很明显:
- 如果有多个程序都需要用到同一个函数,譬如printf;那么所有使用了printf的程序都需要有一份printf.o的副本。比较占空间。
- 更新⽐较困难:每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程序。
但,静态链接一般速度较快。
动态链接
动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对独⽴部分,在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序,⽽不是像静态链接⼀样把所有程序模块都链接成⼀个单独的可执⾏⽂件。
动态链接的缺点是速度较慢,但是却解决了静态链接出现的问题。
动静态库
函数库一般分为动态库和静态库两种:
- 静态库是指在编译链接时,把库文件的代码全部都加载进入到可执行文件当中,因此生成的文件体积比较大,但是运行的时候也不需要库文件了,静态库一般以.a为后缀。
- 动态库与之相反,在编译链接时没有把库文件的代码加载到可执行文件当中,而是在程序运行时由链接文件加载库,这样可以节省系统的开销,动态库一般以.so为后缀。
Linux调试器—gdb/cgdb
gdb是不带可视化界面的一种调试器,cgdb是带可视化界面的调试器,鄙人更喜欢cgdb。
cgdb安装指令如下:
sudo apt-get install -y cgdb
debug和release
首先,我们应该知道程序是有两个版本的,分别是debug版本和release版本。
- debug:程序本身带有调试信息,可以进行调试。
- release:程序本身不添加调试信息,无法进行调试。
在Linux当中gcc/g++默认生成的程序是release版本的,也就是说,是无法被调试的,如果想要生成的程序可以调试,需要加上-g选项。
如下:
gcc test.c -o test -g
这样,生成的程序就是可以被调试的了。
gdb命令
- 进入gdb
gdb 文件名
- 调试
run/r:启动调试
next/n:逐过程调试
step/s:逐语句调试
until 行号:跳转
finish:执行完当前运行的函数后停止
continue/c:执行到下一个断点处
set var 变量=x:修改变量的值
- 显示
list/l n:显示从第n行开始的源代码,每次显示10行。若n未给出则默认从上次的位置继续往下查
list/l 函数名:显示函数的源代码
print/p 变量:打印变量的值
display 变量:将变量加入常显示,即每次停止都打印一次
undisplay 编号:取消指定编号变量的常显示
bt:查看各级函数调用以及参数
info/i locals:查看当前栈帧中局部变量的值
- 断点
break/b n:在第几行设置断点
break/b 函数名:在函数体内的第一行设置断点
info breakpoint/b:查看已设置的断点信息
delete/d 编号:删除指定编号的断点
disable 编号: 禁用指定编号的断点
enable 编号: 启用指定编号的断点
- 退出gdb
quit/q:退出gdb
Linux 项目自动化构建工具–make/Makefile
在 Linux 项目开发中,make 和 Makefile 作为自动化构建的核心工具,极大地提升了开发效率,尤其在处理大型复杂工程时,其优势更为显著。
make/Makefile 的作用
在大型工程里,源文件通常会依据类型、功能和模块等维度,分散存储在多个不同目录中。Makefile 则通过精心定义一系列规则,精确指定了各个文件的编译顺序,从先编译哪些文件到后编译哪些文件,甚至对于更为复杂的操作流程,也能进行妥善处理。
使用 Makefile 的最大好处在于实现了“自动化编译”。开发者只需提前编写好 Makefile 文件,随后仅需执行一次 make 命令,整个工程就能自动完成编译过程。这种方式有效避免了手动编译的繁琐操作以及重复劳动,从而大幅提升了开发效率。(make命令只会执行第一个任务)
make 是一个命令行工具,专门用于解释并执行 Makefile 中所定义的指令。可以说,make 是执行命令的工具,而 Makefile 则是存储编译规则的文件。能否熟练编写 Makefile,在很大程度上反映了一个开发者是否具备处理大型工程的能力。
依赖关系和依赖方法
在使用 make 和 Makefile 之前,深入理解文件之间的依赖关系和依赖方法是至关重要的。
依赖关系
依赖关系描述了文件之间的依存关联。具体而言,如果文件 A 的内容发生变更会对文件 B 产生影响,那么我们就称文件 B 依赖于文件 A。
例如,在编译过程中,test.o 文件是通过对 test.c 文件进行预处理、编译、汇编等一系列操作后生成的。因此,我们可以明确地说 test.o 依赖于 test.c。
依赖方法
依赖方法指的是从一个文件(源文件)生成另一个文件(目标文件)所采用的具体工具或命令的操作过程。以 test.o 和 test.c 为例,test.o 依赖于 test.c,而通过执行 gcc -c test.c -o test.o
这条命令,就能够实现从 test.c 生成 test.o 的过程,这一过程就是我们所说的依赖方法。
基本使用
代码文件 (myproc.c)
#include <stdio.h>
int main() {
printf("hello, world!\n");
return 0;
}
Makefile 文件
myproc: myproc.c
gcc -o myproc myproc.c
.PHONY: clean
clean:
rm -f myproc
依赖关系与依赖方法及相关原理
依赖关系
在上述示例中,myproc
可执行文件依赖于 myproc.c
源文件。
依赖方法
编译生成 myproc
的依赖方法是通过执行 gcc -o myproc myproc.c
这条命令来实现的。
为什么要写 clean
在工程开发中,clean
任务的主要功能是清理编译过程中生成的目标文件和中间文件。添加 clean
目标的原因如下:
- 工程构建完成后,为保持项目目录整洁、节省磁盘空间,通常需清理生成的目标文件和中间文件。
clean
目标未被其他目标直接或间接依赖,其定义的命令不会自动执行。开发者需显式执行make clean
来清理目标文件,以便重新编译。- 为确保
clean
任务每次执行make clean
时都被执行,使用.PHONY
将其标记为伪目标。伪目标无论文件时间戳如何,相关命令都会执行。
总是被执行的含义
若未使用 .PHONY
标记,make
依据目标文件时间戳判断是否执行任务。若文件时间戳显示为最新,make
不重新执行任务。但 clean
任务不生成文件,我们希望每次都执行清理操作,不受时间戳影响。所以用 .PHONY
标记 clean
,保证每次执行 make clean
时都会执行清理。
make 原理
下面我们阐述下make原理:
1.查找 Makefile
make
会在当前目录查找名为 Makefile
或 makefile
的文件。
2.解析第一个目标文件
若找到 Makefile
,make
会读取第一个目标文件(target)。如上述例子,会找到 myproc
作为最终目标文件。
3.检查文件是否需要更新
- 若
myproc
文件不存在,或其依赖文件(如myproc.o
)修改时间比myproc
新,make
会执行命令生成myproc
。 - 若
myproc
文件存在且时间戳最新,make
会跳过生成过程(.PHONY
标记的目标除外,会始终执行)。
4.递归生成依赖文件
若 myproc
依赖的 myproc.o
文件不存在,make
会在 Makefile
中查找生成规则并生成该文件。
- 最终生成目标文件
在依赖关系链最后,make
生成目标文件myproc
。若依赖文件存在且未修改,直接使用现有文件。
6.错误处理
- 查找依赖关系时,若某个依赖文件找不到,
make
会退出并报错。 - 若命令定义有误或编译失败,
make
会忽略错误,不再继续执行。
7.依赖性判断
make
主要关注文件依赖性。源文件和目标文件时间戳相同,make
认为目标文件是最新的,不执行任务;源文件较新时,make
重新执行命令。
.PHONY 伪目标
.PHONY 介绍
.PHONY
是 Makefile
文件中的关键字,用于声明某个目标为伪目标。伪目标不对应实际文件,无论文件是否修改,相关命令每次都会执行。
如何使用 .PHONY
.PHONY: clean
clean:
rm -rf myproc
在这个例子中,clean 是伪目标,用于清理生成的目标文件。即便没有名为 clean 的文件,执行 make clean 时,删除命令也会始终执行。
.PHONY 的作用
使用 .PHONY 可忽略文件时间戳判断,强制每次执行任务。通常将 clean 任务定义为 .PHONY 伪目标,确保每次执行 make clean 时清除目标文件,为重新编译做准备。
我们可以用stat看到如下:
$ stat XXX
File: ‘XXX’
Size: 987 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1321125 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ whb) Gid: ( 1000/ whb)
Access: 2024-10-25 17:05:30.430619002 +0800
Modify: 2024-10-25 17:05:25.940595116 +0800
Change: 2024-10-25 17:05:25.940595116 +0800
⽂件 = 内容 + 属性
Modify: 内容变更,时间更新
Change:属性变更,时间更新
Access:常指的是⽂件最近⼀次被访问的时间。在Linux的早期版本中,每当⽂件被访问时,其atime
都会更新。但这种机制会导致⼤量的IO操作。具体更新原则,不做过多解释。
PHONY:让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐