【Linux】基础开发⼯具
前言
本章节咱们来具体学习一下Linux系统下的基础开发工具,主要从以下几个工具开始讲:软件包管理器、编辑器Vim、编译器g++/gcc、构建自动化makefile、Linux第一个系统程序-进度条、第6个版本控制器Git、调试器-gdb/cgdb使用。
1. 软件包管理器
1-1 什么是软件包
在Linux下安装软件, ⼀个通常的办法是下载到程序的源代码, 并进⾏编译, 得到可执⾏程序
但是这样太⿇烦了, 于是有些⼈把⼀些常⽤的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在⼀个服务器上, 通过包管理器可以很⽅便的获取到这个编译好的软件包, 直接进⾏安装.
软件包和软件包管理器, 就好⽐ "App" 和 "应⽤商店" 这样的关系.
yum(Yellow dog Updater, Modified)是Linux下⾮常常⽤的⼀种包管理器. 主要应⽤在Fedora,RedHat, Centos等发⾏版上.
Ubuntu:主要使⽤apt(Advanced Package Tool)作为其包管理器。apt同样提供了⾃动解决依
赖关系、下载和安装软件包的功能。
1-2 Linux软件⽣态
Linux下载软件的过程(Ubuntu、Centos、other)

操作系统的好坏评估--- ⽣态问题

为什么会有⼈免费特定社区提供软件,还发布?还提供云服务器让你下载?主要是开源精神和维护自己的生态。

常用国内镜像站:
-
阿里云镜像站:https://developer.aliyun.com/mirror/
-
清华大学镜像站:https://mirrors.tuna.tsinghua.edu.cn/
-
中科大镜像站:http://mirrors.ustc.edu.cn/
1-3. yum/apt 基本操作
查看软件包
bash
# CentOS
yum list | grep 软件名
# Ubuntu
apt search 软件名
apt show 软件名

安装软件
bash
# CentOS
sudo yum install -y 软件名
# Ubuntu
sudo apt install -y 软件名

卸载软件
bash
# CentOS
sudo yum remove -y 软件名
# Ubuntu
sudo apt remove -y 软件名

2、Vim编辑器
1. Vim三种核心模式
我们讲解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

2. 模式切换
首先我们创建一个.c文件,接着利用vim打开文件,进入默认是命令模式



3. 常用命令
vim正常模式命令集
• 插⼊模式
• 按「i」切换进⼊插⼊模式「insert mode」,按“i”进⼊插⼊模式后是从光标当前位置开始输⼊
⽂件;
• 按「a」进⼊插⼊模式后,是从⽬前光标所在位置的下⼀个位置开始输⼊⽂字;
• 按「o」进⼊插⼊模式后,是插⼊新的⼀⾏,从⾏⾸开始输⼊⽂字。
• 从插⼊模式切换为命令模式
• 按「ESC」键。
• 移动光标
• vim可以直接⽤键盘上的光标来上下左右移动,但正规的vim是⽤⼩写英⽂字⺟「h」、「j」、
「k」、「l」,分别控制光标左、下、上、右移⼀格
• 按「G」:移动到⽂章的最后
• 按「 $ 」:移动到光标所在⾏的“⾏尾”
• 按「^」:移动到光标所在⾏的“⾏⾸”
• 按「w」:光标跳到下个字的开头
• 按「e」:光标跳到下个字的字尾
• 按「b」:光标回到上个字的开头
• 按「#l」:光标移到该⾏的第#个位置,如:5l,56l
• 按[gg]:进⼊到⽂本开始
• 按[shift+g]:进⼊⽂本末端
• 按「ctrl」+「b」:屏幕往“后”移动⼀⻚
• 按「ctrl」+「f」:屏幕往“前”移动⼀⻚
• 按「ctrl」+「u」:屏幕往“后”移动半⻚
• 按「ctrl」+「d」:屏幕往“前”移动半⻚
• 删除⽂字
• 「x」:每按⼀次,删除光标所在位置的⼀个字符
387
• 「#x」:例如,「6x」表⽰删除光标所在位置的“后⾯(包含⾃⼰在内)”6个字符
• 「X」:⼤写的X,每按⼀次,删除光标所在位置的“前⾯”⼀个字符
• 「#X」:例如,「20X」表⽰删除光标所在位置的“前⾯”20个字符
• 「dd」:删除光标所在⾏
• 「#dd」:从光标所在⾏开始删除#⾏
• 复制
• 「yw」:将光标所在之处到字尾的字符复制到缓冲区中。
• 「#yw」:复制#个字到缓冲区
• 「yy」:复制光标所在⾏到缓冲区。
• 「#yy」:例如,「6yy」表⽰拷⻉从光标所在的该⾏“往下数”6⾏⽂字。
• 「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与“y”有关的复制命令都必须
与“p”配合才能完成复制与粘贴功能。
• 替换
• 「r」:替换光标所在处的字符。
• 「R」:替换光标所到之处的字符,直到按下「ESC」键为⽌。
• 撤销上⼀次操作
• 「u」:如果您误执⾏⼀个命令,可以⻢上按下「u」,回到上⼀个操作。按多次“u”可以执⾏
多次回复。
• 「ctrl + r」: 撤销的恢复
• 更改
• 「cw」:更改光标所在处的字到字尾处
• 「c#w」:例如,「c3w」表⽰更改3个字
• 跳⾄指定的⾏
• 「ctrl」+「g」列出光标所在⾏的⾏号。
• 「#G」:例如,「15G」,表⽰移动光标⾄⽂章的第15⾏ ⾸。
在使⽤末⾏模式之前,请记住先按「ESC」键确定您已经处于正常模式,再按「:」冒号即可进⼊末⾏
模式。
• 列出⾏号
• 「set nu」: 输⼊「set nu」后,会在⽂件中的每⼀⾏前⾯列出⾏号。
• 跳到⽂件中的某⼀⾏
388
• 「#」:「#」号表⽰⼀个数字,在冒号后输⼊⼀个数字,再按回⻋键就会跳到该⾏了,如输⼊数字
15,再回⻋,就会跳到⽂章的第15⾏。
• 查找字符
• 「/关键字」: 先按「/」键,再输⼊您想寻找的字符,如果第⼀次找的关键字不是您想要的,可以
⼀直按「n」会往后寻找到您要的关键字为⽌。
• 「?关键字」:先按「?」键,再输⼊您想寻找的字符,如果第⼀次找的关键字不是您想要的,可
以⼀直按「n」会往前寻找到您要的关键字为⽌。
• 问题:∕ 和 ?查找有和区别?操作实验⼀下
• 保存⽂件
• 「w」: 在冒号输⼊字⺟「w」就可以将⽂件保存起来
• 离开vim
• 「q」:按「q」就是退出,如果⽆法离开vim,可以在「q」后跟⼀个「!」强制离开vim。
• 「wq」:⼀般建议离开时,搭配「w」⼀起使⽤,这样在退出的时候还可以保存⽂件。
3、GCC/G++编译器
1. 编译过程
C/C++程序编译分为四个阶段:
预处理
bash
gcc -E hello.c -o hello.i
宏替换、头文件展开、条件编译、去注释
编译
bash
gcc -S hello.i -o hello.s
语法检查、代码优化、生成汇编代码
汇编
bash
gcc -c hello.s -o hello.o
将汇编代码转换为机器码,生成目标文件
链接
bash
gcc hello.o -o hello
将目标文件和库文件链接生成可执行文件
2. 静态链接 vs 动态链接
在我们的实际开发中,不可能将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽且多个源⽂件之间不是独⽴的,⽽会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数,但是每个源⽂件都是独⽴编译的,即每个*.c⽂件会形成⼀个*.o⽂件,为了满⾜前⾯说的依赖关系,则需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。这个链接的过程就是静态链接。静态链接的缺点很明显:
• 浪费空间:因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本,所以如果多个程序对
同⼀个⽬标⽂件都有依赖,如多个程序中都调⽤了printf()函数,则这多个程序中都含有printf.o,所以同⼀个⽬标⽂件都在内存存在多个副本;
• 更新⽐较困难:因为每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程
序。但是静态链接的优点就是,在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西,在执⾏的时候运⾏速度快。
动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对独⽴部分,在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序,⽽不是像静态链接⼀样把所有程序模块都链接成⼀个单独的可执⾏⽂件。
动态链接其实远⽐静态链接要常⽤得多。⽐如我们查看下 hello 这个可执⾏程序依赖的动态库,会发现它就⽤到了⼀个c动态链接库:

在这⾥涉及到⼀个重要的概念: 库
• 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该
函数的声明,⽽没有定义函数的实现,那么,是在哪⾥实“printf”函数的呢?
• 最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库⽂件中去了,在没有特别指定
时,gcc 会到系统默认的搜索路径“/usr/lib”下进⾏查找,也就是链接到 libc.so.6 库函数中去,这样
就能实现函数“printf”了,⽽这也就是链接的作⽤
3.静态库和动态库
• 静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运
⾏时也就不再需要库⽂件了。其后缀名⼀般为“.a”
• 动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是在程序执⾏时由
运⾏时链接⽂件加载库,这样可以节省系统的开销。动态库⼀般后缀名为“.so”,如前⾯所述的
libc.so.6 就是动态库。gcc 在编译时默认使⽤动态库。完成了链接之后,gcc 就可以⽣成可执⾏⽂
件,如下所⽰。 gcc hello.o –o hello
• gcc默认⽣成的⼆进制程序,是动态链接的,这点可以通过 file 命令验证。
小总结:
静态链接
编译时把库代码全部加入可执行文件
优点:运行时不需要外部库,执行速度快
缺点:文件体积大,更新困难
后缀:.a(Linux)、.lib(Windows)
动态链接
编译时只记录库信息,运行时加载
优点:文件小,多个程序可共享库
缺点:运行时需要库文件存在
后缀:.so(Linux)、.dll(Windows)
4. 常用编译选项及检查文件类型和依赖-了解
• -E 只激活预处理,这个不⽣成⽂件,你需要把它重定向到⼀个输出⽂件⾥⾯
• -S 编译到汇编语⾔不进⾏汇编和链接
• -c 编译到⽬标代码
• -o ⽂件输出到 ⽂件
• -static 此选项对⽣成的⽂件采⽤静态链接
• -g ⽣成调试信息。GNU 调试器可利⽤该信息。
• -shared 此选项将尽量使⽤动态库,所以⽣成⽂件⽐较⼩,但是需要系统由动态库.
• -O0
• -O1
• -O2
• -O3 编译器的优化选项的4个级别,-O0表⽰没有优化,-O1为缺省值,-O3优化级别最⾼
• -w 不⽣成任何警告信息。
• -Wall ⽣成所有警告信息
bash
# 检查文件类型
file 可执行文件
# 查看动态库依赖
ldd 可执行文件
4、自动化构建工具 - Makefile
1. Makefile基本概念
会不会写makefile,从⼀个侧⾯说明了⼀个⼈是否具备完成⼤型⼯程的能⼒
• ⼀个⼯程中的源⽂件不计数,其按类型、功能、模块分别放在若⼲个⽬录中,makefile定义了⼀
系列的规则来指定,哪些⽂件需要先编译,哪些⽂件需要后编译,哪些⽂件需要重新编译,甚⾄于进⾏更复杂的功能操作
• makefile带来的好处就是⸺“⾃动化编译”,⼀旦写好,只需要⼀个make命令,整个⼯程完全⾃动编译,极⼤的提⾼了软件开发的效率。
• make是⼀个命令⼯具,是⼀个解释makefile中指令的命令⼯具,⼀般来说,⼤多数的IDE都有这个命令,⽐如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可⻅,makefile都成为了⼀种在⼯程⽅⾯的编译⽅法。
• make是⼀条命令,makefile是⼀个⽂件,两个搭配使⽤,完成项⽬⾃动化构建。
Makefile:定义编译规则的文件,实现"自动化编译"
make:解释Makefile中指令的命令工具
2. 基本语法规则
实例代码

依赖关系
• 上⾯的⽂件code,它依赖code.c
依赖⽅法
• gcc -o code code.c ,就是与之对应的依赖关系
项⽬清理
• ⼯程是需要被清理的
• 像clean这种,没有被第⼀个⽬标⽂件直接或间接关联,那么它后⾯所定义的命令将不会被⾃动
执⾏,不过,我们可以显⽰要make执⾏。即命令⸺“make clean”,以此来清除所有的⽬标⽂件,以便重编译。
• 但是⼀般我们这种clean的⽬标⽂件,我们将它设置为伪⽬标,⽤ .PHONY 修饰,伪⽬标的特性是,总是被执⾏的。
• 可以将我们的 hello ⽬标⽂件声明成伪⽬标,测试⼀下。
什么叫做总是被执⾏?
$ 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时间对⽐
4-4 推导过程

• make是如何⼯作的,在默认的⽅式下,也就是我们只输⼊make命令。那么:
1. make会在当前⽬录下找名字叫“Makefile”或“makefile”的⽂件。
2. 如果找到,它会找⽂件中的第⼀个⽬标⽂件(target),在上⾯的例⼦中,他会找到 myproc 这
个⽂件,并把这个⽂件作为最终的⽬标⽂件。
3. 如果 myproc ⽂件不存在,或是 myproc 所依赖的后⾯的 myproc.o ⽂件的⽂件修改时间要
⽐ myproc 这个⽂件新(可以⽤ touch 测试),那么,他就会执⾏后⾯所定义的命令来⽣成
myproc 这个⽂件。
4. 如果 myproc 所依赖的 myproc.o ⽂件不存在,那么 make 会在当前⽂件中找⽬标为
myproc.o ⽂件的依赖性,如果找到则再根据那⼀个规则⽣成 myproc.o ⽂件。(这有点像⼀
个堆栈的过程)
5. 当然,你的C⽂件和H⽂件是存在的啦,于是 make 会⽣成 myproc.o ⽂件,然后再⽤
myproc.o ⽂件声明 make 的终极任务,也就是执⾏⽂件 hello 了。
6. 这就是整个make的依赖性,make会⼀层⼜⼀层地去找⽂件的依赖关系,直到最终编译出第⼀个
⽬标⽂件。
7. 在找寻的过程中,如果出现错误,⽐如最后被依赖的⽂件找不到,那么make就会直接退出,并
报错,⽽对于所定义的命令的错误,或是编译不成功,make根本不理。
397
8. make只管⽂件的依赖性,即,如果在我找了依赖关系之后,冒号后⾯的⽂件还是不在,那么对
不起,我就不⼯作啦。
3 适度扩展语法

5.Linux第⼀个系统程序−进度条
我自己实现的:study/0921/process.c · 毅哥/linux_learning - 码云 - 开源中国
6、版本控制工具 Git
1. Git基本概念
不知道你⼯作或学习时,有没有遇到这样的情况:我们在编写各种⽂档时,为了防⽌⽂档丢失,更改失误,失误后能恢复到原来的版本,不得不复制出⼀个副本,⽐如:
“报告-v1”
“报告-v2”
“报告-v3”
“报告-确定版”
“报告-最终版”
“报告-究极进化版”
...
每个版本有各⾃的内容,但最终会只有⼀份报告需要被我们使⽤ 。
但在此之前的⼯作都需要这些不同版本的报告,于是每次都是复制粘贴副本,产出的⽂件就越来越
多,⽂件多不是问题,问题是:随着版本数量的不断增多,你还记得这些版本各⾃都是修改了什么
吗?⽂档如此,我们写的项⽬代码,也是存在这个问题的!!
为了能够更⽅便我们管理这些不同版本的⽂件,便有了版本控制器。所谓的版本控制器,就是能让你了解到⼀个⽂件的历史,以及它的发展过程的系统。通俗的讲就是⼀个可以记录⼯程的每⼀次改动和版本迭代的⼀个管理系统,同时也⽅便多⼈协同作业。
⽬前最主流的版本控制器就是 Git 。Git 可以控制电脑上所有格式的⽂件,例如 doc、excel、dwg、dgn、rvt等等。对于我们开发⼈员来说,Git 最重要的就是可以帮助我们管理软件开发项⽬中的源代码⽂件!
版本控制:管理文件历史和发展过程的系统
Git特点:分布式、速度快、支持非线性开发
2. 基本工作流程
首先安装git:yum install git,其次你得有一个仓库,简单来说就是有一个gitte账户,然后这个账户下创建一个云仓库,之后通过Linux系统里的git将你的文件夹和仓库关联起来,以后就可以将本地文件保存到云仓库上,两者是互通的,且一个仓库可以对用多个本地。
克隆项目
bash
git clone [项目URL]
三板斧操作
bash
# 1. 添加文件到暂存区
git add [文件名]
git add . # 添加所有文件
# 2. 提交到本地仓库
git commit -m "提交说明"
# 3. 推送到远程仓库
git push
3. 其他常用命令
bash
git status # 查看状态
git log # 查看提交历史
git pull # 拉取远程更新
七、调试器 GDB

1. 准备工作
程序的发布⽅式有两种, debug 模式和 release 模式, Linux gcc/g++ 出来的⼆进制程
序,默认是 release 模式。
• 要使⽤gdb调试,必须在源代码⽣成⼆进制程序的时候, 加上 -g 选项,如果没有添加,程序⽆法被编译,编译时必须添加-g选项生成调试信息:
bash
gcc -g mycmd.c -o mycmd # 支持调试
gcc mycmd.c -o mycmd # 不支持调试

2. 常用调试命令



上⾯的基本调试还是⿇烦,虽然是⿊屏,但是还是想看到代码调试
• 推荐安装cgdb:
• Ubuntu: sudo apt-get install -y cgdb
• Centos: sudo yum install -y cgdb
指令还是和上表一样的!
总结:
通过本章学习,我们系统掌握了Linux环境下必备的开发工具链:从软件包管理器yum/apt的基础操作,到Vim编辑器的多模式高效使用;从GCC编译器的四阶段编译原理,到Makefile的自动化构建技巧;再到进度条程序的缓冲区控制、Git版本管理的三板斧工作流,以及GDB调试器的核心调试方法。这些工具共同构成了Linux开发的基础设施,熟练掌握它们将极大提升开发效率和问题解决能力,为后续更深入的Linux系统编程和项目开发奠定坚实基础。如果你觉得本文讲得不错的话,请留下点赞和收藏吧,谢谢支持!
