Linux系统:基本开发工具
基础开发
Windows 下有例如 Visual Studio、IDEA 这样的集编写代码、编译代码、调试代码、运行代码、代码关系维护以及各种各样的复杂功能于一身的开发工具,叫做集成开发环境 IDE。Linux 下一般使用代码编辑工具 vi/vim,编译工具 gcc/g++,调试工具 gdb。
1. 编辑工具 vim
Linux 下编写代码使用 vi/vim,它是一款多模式的十分强大的文本编辑器,所有的类 unix 系统都会内置 vi 编辑器,目前使用较多的是 vim 编辑器,也就是 vi 的升级版。虽说 vim 是个文本编辑器,但它更专注于代码的编写,具有语法高亮等功能。
$ vim fileName
输入上述命令即可将使用 vim 打开文件,文件不存在则会创建文件。
1.1 vim 的基本模式
vim 基本的模式有三:命令模式(normal mode)插入模式(insert mode)底行模式(command mode),vim 刚启动时,就进入命令模式。
命令模式下输入
i
可以进入输入模式,再按Esc
键就可以回退到命令模式。命令模式下输入
:
即可进入底行模式,再按Esc
键就可以回退到命令模式。底行模式下输入
wq
可以保存退出。
知悉上述基本的模式切换方法后,再逐个介绍模式。
命令模式(normal)
vim 刚启动时,就进入命令模式。此状态下敲击键盘动作会被 Vim 识别为命令,而非输入字符。可进行的操作有:控制光标移动,字符、单词或行的删改,移动或复制粘贴文本内容,切换到插入或底行模式。
底行模式(command)
命令模式只有一些最基本的命令,因此仍要依靠底线命令模式输入更多命令。命令模式下输入:
即可进入底行模式,底线命令模式可以输入多个字符的命令,可用的命令非常多。
插入模式(insert)
文本编辑模式。一般要先退回到命令模式才能进到底行模式。
vim 总共有13种模式,但这三个基本模式已经能满足我们大部分需求,其他模式会在之后的使用中学习。
1.2 vim 正常模式命令集
切换模式
- 切换到插入模式
i
,a
,o
或底行模式Esc
。 i
选项是从光标的位置开始输入,a
选项会将光标向后移动一位,o
选项在光标的下方另起一行。Esc
退回到命令模式后向前移动一位。
光标移动
- ⬅
H
、⬇J
、⬆K
、➡L
,相当于方向键。 - 光标锚点跳至行首
^
、行尾$
;跳至文章起始gg
、末尾G
;跳至指定行n+gg
/n+G
。 - 移动到下一个单词的起始
w
,移动到下一个单词的末尾e
,反向单词距移动b
,字符、字母、字母数字组合都被视为单词。 Ctrl+B
光标向下翻页,Ctrl+F
向上翻页;Ctrl+U
向下移动半页,Ctrl+D
向上移动半页。
删改内容
- 删除当前字符
x
,多个字符n+x
;反向删除字符X
,多个字符n+X
。 - 删除单词
dw
,删除当前行dd
。 - 替换当前字符
r
,多个字符n+r
,进入替换模式R
。 - 修改当前单词
cw
,修改多个单词cnw
。 - 字母大小写转换
~
。
移动或复制内容
- 复制光标位置当前单词
yw
,多个单词n+yw
。 - 复制当前行
yy
,复制多行n+yy
。 - 剪切/删除当前行
dd
,剪切多行n+dd
。 - 粘贴到当前行下方
p
,粘贴多次n+p
。
撤销操作
u
,恢复操作Ctrl+r
。
1.3 vim 底行模式命令集
保存退出
- 底行模式下输入
w
可以保存文件,输入q
可以退出程序。带上!
表示强制执行。
显式行号
- 显示行号
set nu
,取消行号set nonu
。 - 跳转至某行,输入行号
n
即可。
多文件操作
- 分屏操作多个文件
vs fileName
,切换操作文件/光标Ctrl+w+w
。
查找字符
/Keyword
,输入/
再输入查找的字符,在按n
可以跳转至下一个关键字所在位置。?keyword
,输入/
再输入查找的字符,在按n
可以跳转至上一个关键字所在位置。- 可直接使用
shift+*
,查找当前光标所在的单词。
底行模式命令有很多,目前掌握这几个就行。
Vim 从入门到精通 (github.com)
最全 Vim 键位图 (runoob.com)
2. 编译工具 gcc/g++
gcc/g++ 分别是 C/C++ 的编译器,基本使用方法:
$ gcc [选项] 编译文件 [选项] 目标文件
$ g++ [选项] 编译文件 [选项] 目标文件
接下来将通过使用 gcc 分段编译程序,来熟悉 gcc/g++ 的使用。
2.1 C/C++编译基本步骤
前面已经学过 C/C++ 程序基本的编译过程,也使用过 gcc 进行查看程序的翻译步骤:
- 预处理(进行宏替换)
- 编译(生成汇编代码)
- 汇编(生成机器可识别的二进制文件)
- 链接(生成可执行文件或库文件)
预处理
- 预处理的功能主要包括宏定义,文件包含,条件编译,删除注释等。预处理指令主要指以
#
开头的语句。
$ gcc -E test.c -o test.i # 完成预处理后停止
- 选项
-E
让翻译在预处理结束后停下来,-o
可以指定生成的目标文件名,预处理完的文件一般后缀为.i
。
编译
- 编译时,gcc 会检查代码的规范性、是否有语法错误,已确定代码所做的工作,检查无误后 gcc 会生成汇编代码。
$ gcc -S test.i -o test.s # 完成编译后停止
- 编译阶段会生成汇编代码,以供接下来的汇编阶段使用。一般编译结束生成的代码文件的后缀为
.s
。
汇编
- 汇编阶段将编译所形成的汇编代码生成目标文件,也就是二进制文件。
$ gcc -c test.s -o test.o # 完成汇编后停止
虽然生成的是二进制目标文件,但仍然不可直接运行,准确的来说该文件是可重定向目标文件。相当于Windows下的.obj
文件。
链接
预处理、编译、汇编三个阶段统称为编译过程,完成了上述编译的过程,就到了翻译环境的最后一个阶段:链接。链接完成之后,就生成了可执行文件。
$ gcc test.o -o test # 完成链接
链接是将所有.c
源文件所生成的目标文件与语言的链接库文件放到一起进行链接。如图所示:
通常写程序时,就
include
了语言本身所提供的链接库文件,至于链接库文件到底是什么,接下来会讲解。
当然编译 C/C++ 程序,不需要上述这么复杂,直接执行即可:
$ gcc test.c -o test # 1.
$ gcc -o test test.c # 2.
2.2 静态链接和动态链接
函数库的概念
语言本身会提供的库,库可以看成一套头文件和一套库文件。比如通常使用的printf
,scanf
等等库函数,都是实现在库文件中的,可以通过引用对应的头文件,来使用这些代码。
使用lld
命令可以查看可执行程序所依赖的第三方库:
Linux 下的C语言的库文件一般叫作libc.a
和libc.so
,分别是静态库和动态库。Windows 下的静态库和动态库的后缀分别为.lib
和.dll
。
将用户所写的程序文件和第三方库提供的方法关联起来,这就叫链接。很显然,链接又分为静态链接和动态链接。
由上图可以看出,gcc 默认形成的可执行程序,采用动态链接的方式,因为可执行程序依赖的是动态库。
$ gcc test.c -o test # 默认动态方式
$ gcc test.c -o test_static -static # 采用静态方式
静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时,下面来详细介绍这两种链接方式。
静态链接
一般开发时,会将代码分离编写到多个.c
源文件中,而这多个源文件之间不是独立的,可能某个源文件要调用另一个源文件中的函数。
这个调用就发生在目标文件的链接过程中,由链接器在链接时将库的内容拷贝到可执行程序中。然后才能生成可执行程序文件,所以说静态链接发生在形成可执行程序之前。
由上图可以看出,静态链接生成的文件比动态链接的体积大得多。
静态链接的优缺点
静态链接的缺点很明显:
- 浪费空间,链接时会将库中的内容放入目标文件中,所以文件的体积较大。如果有多个程序文件,那么每个程序中都会加入库文件的内容,包含相同的公共代码,造成浪费。
- 更新较为麻烦,每当库函数的代码修改了,此时就需要重新进行重新打包成
lib
文件,再去编译链接形成可执行程序。
静态链接的优点是,在可执行程序中已经具备了所有执行程序所需要的任何东西,不需要到其他文件中查找内容,在执行的时候运行速度快。
动态链接
动态链接出现就是为了解决静态链接中的两个问题:空间浪费和更新困难。 动态链接把程序按照模块拆分成各个相对独立部分,并把链接这个过程推迟到了运行时再进行,由操作系统的装载程序加载库,将它们链接在一起形成一个完整的程序。
假设有两个程序都包含同一个库文件,运行程序1时会将程序1加载到内存中,然后再加载该库文件,再运行程序2时,内存中已有库文件就不会再次加载,直接链接到程序2中即可。
动态链接的优缺点
动态链接的优点是:
- 避免空间浪费,即使多个程序依赖于同一个库,但该库不会像静态链接那样在内存中存在多份副本,而是这多个程序执行时共享副本。
- 维护比较方便,更新时只需要替换原来的目标文件,程序再次运行时,新的目标文件会自动加载到内存并链接起来。库文件与可执行文件独立,更新库文件不会对程序文件造成影响,提高了可维护性和可扩展性。
动态链接也是有缺点的,因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失,运行速度相对慢一点。
深入浅出静态链接和动态链接 (csdn.net)
2.3 gcc 选项
-E
激活预处理,需手动重定向输出文件;-S
编译到汇编语言;-c
编译到目标代码;-o
文件输出到文件。-static
此选项对生成的文件采用静态链接。-g
生成调试信息,GNU 调试器可利用该信息。-shared
此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库。-O0
,-O1
,-O2
,-O3
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高。-w
不生成任何警告信息,-Wall
生成所有警告信息。
3. 调试工具 gdb
gdb 是 Linux 下用于调试代码的工具,这个工具成本高难度也不低且不是很方便直观但仍需掌握。
3.1 背景知识
程序的发布方式有两种模式:Debug 和 Release 模式。Linux 下 gcc/g++ 编译出的可执行程序,默认是 Release 模式。要使用 gdb 调试,必须在代码编译的时候加上调试信息。
$ gcc test.c -o test_debug -g # 加上调试信息
$ gdb test_debug # 进入gdb调试
(gdb) quit # 退出gdb
3.2 gdb 选项
调试命令(debug)
名称 | 命令 | 解释 |
---|---|---|
开始运行 |
run
|
相当于开始调试F5 ,会运行至程序结束
|
逐语句 |
step
|
相当于F11 ,有函数会进入函数内部
|
逐过程 |
next
|
相当于F10 ,不会进入函数内部,执行整条语句;
|
像逐过程、逐语句这样的命令一次输入之后,可直接回车仍会再次执行。
显示代码(list)
名称 | 命令 | 解释 |
---|---|---|
可指定行号 |
list + [N]
|
从第 N 行开始显示10行代码,省略行号就默认从第一行开始打印,可接着上次的位置继续打印 |
可指定函数名 |
list + Name
|
从函数起始位置左右开始显示代码。 |
断点命令(breakpoint)
名称 | 命令 | 解释 |
---|---|---|
可指定行号 |
b + N
|
在某行打上断点 |
可指定函数名 |
b + Name
|
在函数内起始位置打断点 |
查看断点信息 |
info + b
|
显示断点信息列表 |
删除断点 |
d + b [ + N]
|
删除序号为 N 的断点,省略序号就是删除所有断点 |
启用断点 |
enable + b [ + N]
|
启用序号为 N 的断点,省略序号就是启用所有断点 |
禁用断点 |
disable + b [ + N]
|
禁用序号为 N 的断点,省略序号就是禁用所有断点 |
变量命令(variable)
名称 | 命令 | 解释 |
---|---|---|
监视变量 |
display + Name
|
以列表的形式常显示在屏幕下方,类似于vs中的监视 |
取消监视 |
undisplay + N
|
去掉监视列表中的序号为 N 的变量的常显示 |
查看变量 |
p + Name
|
打印变量的值,不会常显示 |
修改变量 |
set + Name
|
设置指定变量的值 |
特殊调试命令
名称 | 命令 | 解释 |
---|---|---|
结束当前函数 |
finish
|
finish 会直接结束当前函数的调用,并停止在函数返回位置,等待接下来的命令 |
继续调试 |
continue
|
continue 继续运行至下一个断点,相当于F5
|
跳转至指定行 |
until + N
|
跳转至当前函数内部的第 N 行 |
上述三个命令可以快速确定到代码出错的大概范围。finish
和continue
结合在多个函数调用结束的位置检查结果是否正确,定位到出错函数后,可以使用until
在函数内部查找出错位置。
其他命令
名称 | 命令 | 解释 |
---|---|---|
调用堆栈 |
breaktrace /bt
|
查看程序各级栈帧的调用情况 |
4.构建工具 make/Makefile
之前在 IDE 中写代码时,没有关心过文件的编译顺序以及代码的依赖关系,因为 IDE 可以自动构建项目。
4.1 自动化构建工具理解
工程中的源文件不计其数,按类型、功能和模块放在若干目录中,Makefile 文件的内容指定了各个文件编译的先后顺序,甚至更复杂的操作。使用 make 指令就可以自动编译项目文件,但前提是要编写 Makefile 文件。
Makefile 的好处就是“自动化编译”,编写完成后,只需执行 Make 命令,整个项目工程就能够自动编译,极大地提高了软件开发的效率。所以写 Makefile 的能力,从侧面说明了其是否有完成大型项目的能力。
4.2 Makefile 的编写
target : prerequisitescommand
target 也就是目标文件,也可以是执行文件。prerequisites 就是,要生成那个 target 所需要的文件或是目标。command 也就是 make 需要执行的命令。开头第一行写明目标文件 : 依赖文件。第二行以 开头,写明所需命令。
准确地说 Makefile 指明了编译多个代码文件的两个要素:依赖关系和依赖方法。比如可执行文件依赖于源文件,这就是两个文件的依赖关系;通过 gcc 编译源文件可形成可执行文件,这是依赖方法。
mytest:mytest.c # 依赖关系 gcc -o mytest_make mytest.c -std=c99 # 依赖方法
.PHONY:clean
clean: rm -f mytest_make
make 命令用于构建工程,相当于 vs 中的生成解决方案。make clean 用于清理工程,相当于清理解决方案,当然需要自主编写。
- 默认 Makefile 文件第一个目标的是真目标,其他都是伪目标,输入 make 命令默认执行真目标。
.PHONY
是一种关键字,表示其后的目标总是可执行的,一般常用来修饰伪目标。真目标项目为更改情况下只能执行一次,伪目标总是可执行的。
- Makefile中可使用特殊符号:
$@
代表目标文件,$^
代表其后指定的所有依赖文件。
- 如果工程没有编译过,那么所有C文件都要编译并被链接。
- 如果工程的某几个C文件被修改,那么只编译被修改的C文件,并链接目标程序。
- 如果个工程的头文件被改变了,那么需要编译引用了这几个头文件的C文件,并链接目标程序。
4.4 Makefile 的原理
依赖关系和依赖方法
由上图可以看出,
- 依赖关系:
.out
文件依赖.o
文件,.o
文件依赖.s
文件,.s
文件依赖.i
文件,.i
文件依赖.c
文件。 - 依赖方法:
gcc -option hello.* -o hello.*
。
mycode : mycode.ogcc -o mycode.o -c mycode.s
mycode.s : mycode.igcc -o mycode.s -S mycode.i
mycode.i : mycode.cgcc -o mycode.i -E mycode.c
.PHONY:clean
clean:rm -rf mycode.o mycode.s mycode.i
执行 .out 依赖 .o,执行 .o 依赖 .s,执行 .s 依赖 .i,执行 .i 依赖 .c 文件,找到 .c 后再一步一步反向编译到可执行文件。
Makefile 文件可以像上述这样将所有步骤写出来,但一般不这样写,写的越简单越好。
跟我一起写 Makefile (csdn.net)
5. 上传工具 git
创建命令 | 解释 |
---|---|
git init | 新建版本库 |
git clone | 克隆版本库 |
提交命令 | 解释 |
git add | 添加文件到暂存区 |
git commit -m ‘xx’ | 将暂存区文件提交至本地仓库 |
git push | 同步代码至远程仓库 |
git pull | 下载代码至本地仓库 |
git rm | 删除工作区文件。 |
查看命令 | 解释 |
git status | 查看仓库当前的状态,显示有变更的文件 |
git log | 查看仓库提交历史 |
git blame | 以列表形式显示文件修改记录 |
git diff | 比较暂存区和工作区文件的差异 |
分支命令 | 解释 |
git branch | 查看本地所有分支 |
git branch -r | 查看远程所有分支 |
git checkout | 切换所有分支 |
git merge | 合并分支 |
git branch -d | 删除分支 |
github-git-cheat-sheet (runoob.com)
Git - Reference (git-scm.com)
git 简明指南 (runoob.com)
Linux系统:基本开发工具相关推荐
- 【Linux系统】开发工具(上) {软件包管理器yum,更新yum源,文本编辑器vim,vim的四种基本模式,vim指令集,代码编译器gcc/g++}
一.软件包管理器:yum 1.1 yum是什么? Linux下软件的安装方法: 源码安装:下载源码,在本地自行编译,然后才能安装. rpm安装:红帽软件包管理工具,属于安装包安装. yum安装:本身会 ...
- windows不安装虚拟机如何使用Linux系统作为开发工具?
哈喽,大家好,我是仲一.作为嵌入式开发程序员,常常需要在Linux环境下编译一些代码.安装虚拟机比较方便,但是,太占用内存了.性能不好的电脑开了一台虚拟机后,可能就干不了其他事情了.安装双系统也比较麻 ...
- Linux下C++开发工具介绍
概述 就C++开发工具而言,与Windows下微软(VC, VS2005等)一统天下相比,Linux/Unix下C++开发,可谓五花八门,各式各样.Emacs, vi, eclipse, an ...
- 嵌入式linux系统应用开发
关于嵌入式系统 平时大家说的嵌入式其实范围比较广的,是一种软硬件可裁剪,以应用为中心开发的专用系统,硬件平台可以是单片机,或者以ARM系列的处理器.单片机一般直接裸奔程序,不过现在有了好多基于单片 ...
- L1D1:嵌入式Linux C语言开发工具及基础命令
嵌入式Linux C语言开发工具及基础命令 一.ubuntu环境搭建 请自行准备VMware workstation15安装包 及 ubuntu18.04.iso镜像文件.可参考链接:VMware W ...
- STM32MP157 Linux系统移植开发篇4: BootLoader(Uboot)移植
本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...
- 2 Linux环境基础开发工具
2 Linux环境基础开发工具 2.1 Linux软件包管理器yum 2.1.1 软件安装的方式 1. 源码安装 大多数开源的软件都是源码的形式.拿过来自己编译,安装. 优点:源码安装兼容性好. 缺点 ...
- STM32MP157 Linux系统移植开发篇17:Linux内核摄像头驱动移植
本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...
- STM32MP157 Linux系统移植开发篇14:Linux内核RGB LCD驱动移植
本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...
- 开发板通过usb连linux,虚拟机Linux系统和开发板通过USB转串口连接的两种方法
通过USB转串口连接虚拟机中的Linux系统和开发板,开始时候总是出现错误,显示什么串口重叠,最后求助高手帮我通过其他连接方式解决了问题,今天在网上查找资料,终于明白了开始错误的原因:开发板提供的驱动 ...
最新文章
- css为元素添加样式,JQuery如何为元素添加样式
- 算术表达式求解背景_1.8 C++算术运算符与表达式
- ACL中的wildcard mask
- 遍历Repeater与ItemDataBound事件发现的几个问题。
- error LNK2001: unresolved external symbol _main
- html源码md风格,code/html.md at master · Rongx/code · GitHub
- 通过getSystemServices获取手机管理大全
- C#通过Redis实现分布式锁
- SQL语句中LEFT JOIN、JOIN、INNER JOIN、RIGHT JOIN的区别?
- leetcode 501. 二叉搜索树中的众数 思考分析
- tp获取referer里的域名_thinkPHP的redirect跳转和referer使用的问题
- 如果每天给你888元,只能看书学习,不能玩手机电脑,你能坚持多少天?
- linux v4l2 示例程序,linux驱动由浅入深系列:camera驱动之二(基于高通平台的V4L2结构及代码分析)...
- spring-boot-starter-parent 包maven依赖报错
- paip.租房宝付房租功能抓包总结
- 小白的web优化之路 一、使用redis来缓存信息
- creo扫描选择多条链作为轨迹_Proe/Creo曲面造型·蓝牙耳机纹理曲面纹理
- R语言检验独立性:卡方检验(Chi-square test)和费舍尔Fisher精确检验分析案例报告
- 【精选】VI手册设计模板合集,附带源文件、预览图、精细分类
- Linux的strings命令_拔剑-浆糊的传说_新浪博客