【Linux】Linux编程基础(vi、gcc、gdb)
编写一个程序,首先是程序的录入,然后是程序的编译,最后是程序的调试。本文介绍进行这三步工作的主要工具:vi、gcc、gdb。
编辑器介绍
Linux提供了一个完整的编辑器家族系列。按功能可以分为两大类:行编辑器(Ed、Ex)和全屏幕编辑器(vi、Emacs)。行编辑器每次只能队一行进行操作,而全屏幕编辑器可以对整个屏幕进行编辑。
vi介绍
vi是全屏幕编辑器中的一种,它有三种模式,分别为命令行模式、插入模式、底行模式。
- 命令行模式:在使用vi编辑器编辑文件时,最初进入的是一般命令行模式。在该模式下,用户可以通过上下移动光标进行删除字符或整行删除等操作,也可以进行复制、粘贴等操作,但无法编辑文字;
- 插入模式:在该模式下,用户才能进行文字的编辑输入,可以通过ESC键回到命令行模式;
- 底行模式:在该模式下,光标位于屏幕的底行。用户可以进行文件保存或退出操作,也可以设置编辑环境,例如寻找字符串、列出行号等。
vi的各模式功能键
命令行模式下的常见功能键:
功能键 | 含义 |
i | 切换到插入模式,此时光标位于开始输入文件处 |
a | 切换到插入模式,并从目前光标所在位置的下一个位置开始输入文字 |
O | 切换到插入模式,且从行首开始插入新的一行 |
Ctrl+b | 屏幕往后翻动一页 |
Ctrl+f | 屏幕往前翻动一页 |
Ctrl+u | 屏幕往后翻动半页 |
Ctrl+d | 屏幕往前翻动半页 |
0 | 光标移到本行的开头 |
G | 光标移动到输入文件的最后 |
nG | 光标移动到第n行 |
$ | 光标移动到所在行的“行尾” |
n<Enter> | 光标向下移动n行 |
/name | 光标之后查找name的字符串 |
?name | 光标之前查找name的字符串 |
x | 删除光标所在位置的“后面”一个字符 |
dd | 删除光标所在行 |
ndd | 从光标所在行开始往下删除n行 |
yy | 赋值光标所在行 |
nyy | 赋值光标所在行开始的下面n行 |
p | 将缓冲区内的字符粘贴到光标所在的位置 |
u | 恢复之前的一个动作 |
插入模式下的功能键只有1个,按ESC键返回命令行模式。
在命令行模式下,按“Shift+:”进入底行模式。底行模式下常见功能键:
功能键 | 含义 |
:w | 将编辑的文件保存在磁盘中 |
:q | 退出vi(系统对修改过的文件给出保存提示) |
:q! | 强制退出vi(不给提示) |
:wq | 存盘后退出 |
:w[filename] | 另存一个名为filename的文件 |
:set nu | 显示行号 |
:set nonu | 取消行号显示 |
其实经过试验,在命令行模式下,就不要用鼠标,所有的东西都通过命令来完成。如果不是vi命令行模式下的功能键,会使vi进入到插入模式。
程序编译与调试
嵌入式系统开发常用的编译工具是gcc,调试工具是gdb,下面一一介绍。
gcc是GNU项目中符合ANSIC标准的编译工具,能够编译由C、C++和Object C等语言编写的程序。gcc又是一个交叉平台编译器,它能够在当前CPU平台上为多种不同体系结构的硬件平台开发软件,因此尤其适合嵌入式领域的开发编译。
下表示gcc支持编译的源文件的后缀名及其解释:
后缀名 | 对应语言 | 后缀名 | 对应语言 |
.c | C源程序 | .s/.S | 汇编语言源程序 |
.C/.cc/.cxx | C++源程序 | .h | 预处理文件 |
.m | Object-C源程序 | .o | 目标文件 |
.i | 经过预处理的C源程序 | .a/.so | 编译后的库文件 |
.ii | 经过预处理的C++源程序 |
gcc编译流程
gcc的编译流程分为四个步骤:预处理->编译->汇编->链接。
- 预处理阶段:编译器将.c代码的stdio.h编译进来,并且用户可以使用gcc的选项“-E”进行查看,该选项的作用是让gcc在预处理结束后停止编译过程;
- 编译阶段:在编译阶段中,gcc首先要检查代码的规范性以及是否有语法错误等,已确定代码实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。用户可以使用“-S”选项进行查看,该选项只进行编译而不进行汇编,生成汇编代码;
- 汇编阶段:汇编阶段是把编译阶段生成的“.s”文件转换成目标文件,用户可使用选项“-c”查看汇编代码转化的后缀名为“.o”的二进制目标代码;
- 链接阶段:编译成功后,就进入了链接阶段。库函数一般分为静态库和动态库两种。
静态库和动态库的区别:
- 静态库在编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时就再也不需要库文件了,其后缀名一般为“.a”;
- 动态库在编译链接时并没有把库函数的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销,动态库的后缀名一般为“.so”。
gcc在编译时,默认使用动态库。
gcc编译选项分析
gcc有100多个可用选项,主要包括总体选项、告警和出错选项、优化选项和系统结构相关选项。下面对每一类中最常用的选项进行介绍。
后缀名 | 对于的语言 |
-c | 只汇编不链接,生成目标文件“.o” |
-S | 只编译不汇编,生成汇编代码“.s” |
-E | 只预处理不编译,生成文件“.i” |
-g | 在可执行程序中包含标准调试信息 |
-o file | 将文件输出到file里 |
-v | 打印编译器内部各编译过程的命令行信息 |
-I dir | 在头文件的搜索路径列表中添加dir目录 |
-L dir | 在库函数的搜索路径列表中添加dir目录 |
-static | 链接静态库 |
-l library | 链接名为library的库文件 |
选项 | 含义 |
-ansi | 支持符合ANSI标准的C程序 |
-pedantic | 允许发出ANSIC标准所列的全部告警信息 |
-pedantic-error | 允许发出ANSIC标准所列的全部错误信息 |
-w | 关闭所有告警 |
-Wall | 允许发出gcc提供的所有有用的报警信息 |
-werror | 把所有的告警信息转换为错误信息,并在告警发生时终止编译过程 |
gcc可以对代码进行优化,它通过编译选项“-On”控制优化代码的生成,其中n是一个代表优化级别的整数。对于不同版本的gcc,n的取值范围及其对应的优化效果可能并不完全相同,比较典型的范围是0-2或0-3。
不同的优化级别对应不同的优化处理工作。例如:优化选项“-O1”主要进行线程跳转和延迟退栈两种优化;优化选项“-O2”除了完成所有的“-O1”级别的优化之外,还要进行一些额外的调整工作,例如处理器指令调度等;优化选项“-O3”则还包括循环开展和其他一些与处理器特性相关的优化工作。
选项 | 含义 |
-mieee-fp/-mno-ieee-fp | 使用/不使用IEEE标准进行浮点数的比较 |
-msoft-float | 输出包含浮点库调用的目标代码 |
-mshort | 将int类型作为16位处理,相当于short int |
-mrtd | 强行将函数参数固定的函数用ret NUM返回,节省调用函数的一条指令 |
-mcpu=type | 针对不同的CPU使用相应的CPU指令。可选择的type有i386、i486、pentium、i686等 |
gcc指令的一般格式为:
gcc [选项] 要编译的文件 [选项] [目标文件]
例如:
gcc hello.c -o hello //将hello.c生成可执行文件(链接动态库)
gcc -static hello.c -o hello //将hello.c生成可执行文件(链接静态库)
gcc -E hello.c -o hello.i //将hello.c只进行预处理,不做其他处理
gcc -S hello.i -o hello.s //将hello.i只编译不汇编,生成汇编代码
gcc -c hello.s -o hello.o //将hello.s只编译不链接
gcc hello.o -o hello //将hello.o链接到函数库,生成可执行文件
[root@localhost ~]# ./filename //执行可执行文件filename
[root@localhost ~]# cat filename //将文件filename内容输出到标准输出设备(屏幕)上
这里区分一些gcc和g++:
gcc和g++都是GNU(一个组织)的编译器。
- 对于.c后缀的文件,gcc把它当做是C程序,g++当做是C++程序;
- 对于.cpp后缀的文件,gcc和g++都会当做c++程序;
- 编译阶段,g++会调用gcc(也就是说);
- 连接阶段,通常会用g++来完成,这是因为gcc命令不能自动和c++程序使用的库连接。
也就是说:
- gcc可以用来编译c++但是它不会自动调用链接的c++库,需要自己手动链接,使用如下命令: gcc -lstdc++ main.cpp;g++则会自动调用链接的c++库,使用的也是gcc命令。但是gcc在编译c程序的时候,它会自动链接c库的。
- gcc可以根据后缀名为.c或.cpp分别按c程序和c++程序来编译;但是g++无论是.c或.cpp都统一按c++程序来编译。而且g++在编译的过程中,其实是调用gcc按照c++程序来编译的。即编译工作最终都是由gcc来完成的。
gdb程序调试
gdb作为GNU开发组织发布的一个UNIX/LINUX下的程序调试工具,提供了强大的调试功能。
由于gdb的目录很复杂,所以就先留个空,以后学习的时候来补。
【Linux】Linux编程基础(vi、gcc、gdb)相关推荐
- Linux 操作系统编程基础知识
Linux操作系统 1.Linux 操作系统编程基础知识 1.3 系统调用和库函数 1.3.1 接口 命令接口:以命令形式呈现在用户面前,方便用户直接或间接控制自己的作业. 程序接口:为应用程序使用系 ...
- Linux网络编程基础知识
Linux网络编程基础知识 1. 协议的概念 1.1 什么是协议 1.2 典型协议 2 网络应用程序设计模式 2.1 C/S模式 2.2 B/S模式 2.3 优缺点 3 分层模型 3.1 OSI七层模 ...
- 「Linux」Linux Shell 编程基础入门
Linux Shell 编程基础入门 1. 变量 1.1 变量定义 1.2 使用变量 1.3 引号 1.4 将命令的结果赋值给变量 1.5 位置参数 1.6 特殊变量及其含义 2. 字符串 2.1 字 ...
- Linux网络编程基础1(网络应用程序设计模式,分层模型,协议格式)
Linux网络编程基础(网络应用程序设计模式,socket编程,inet_pton,inet_ntop,服务端创建连接的过程,客户端创建连接的过程,socket函数封装) 1. 网络应用程序设计模式 ...
- Linux网络编程基础和一步一步学
·Linux网络编程 基础(一) ·Linux网络编程 基础(二) ·Linux网络编程 基础(三) ·Linux网络编程 基础(四) ·Linux网络编程 基础(五) ·Linux网络编程 基础(六 ...
- Linux操作系统编程基础
文章目录 Linux系统开发基础 Linux系统开发概念 进程地址空间 地址空间:内核空间 VS. 用户空间 程序运行:内核态 VS. 用户态 系统调用 虚拟地址VS.物理地址 Linux应用开发环境 ...
- Linux Shell编程基础
linux系统下给命令指定别名alias命令用法: 在linux系统中如果命令太长又不符合用户的习惯,那么我们可以为它指定一个别名.虽然可以为命令建立"链接"解决长文件名的问题,但 ...
- Linux高级编程--01.vi命令
VI是Linux/Unix下标配的一个纯字符界面的文本编辑器.由于不支持鼠标功能,也没有图形界面,相关的操作都要通过键盘指令来完成,需要记忆大量命令.因此很多人不大喜欢它,但同时由于键盘的方式往往比鼠 ...
- Linux网络编程基础
2019独角兽企业重金招聘Python工程师标准>>> (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端 网络程序和普通的程序有一个最大的 ...
- Linux Shell 编程基础详解——吐血整理,墙裂推荐!
第一部分:Linux Shell 简介 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序, ...
最新文章
- python怎样给对象赋值_Python对象赋值、浅拷贝和深拷贝
- leetcode 38. 外观数列 「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下
- 二进制数代替数组做标记
- Oracle优化01-引起数据库性能问题的因素
- Codeforces Round #260 (Div. 1) C. Civilization(dfs+并查集)
- Java 基本类型相互转换
- Mozilla 放出新的 Firefox 3.5 RC 版本(RC 3)
- php event_base_new,php event拓展基本使用
- Kafka 源码分析之网络层(二)
- SQL、NoSQL、NewSQL,论开源之路谁主沉浮
- Linux网络防火墙:iptables与netfilter
- 【限时免费】云计算时代的安全和智能运维(11月18日周六|广州)
- 2021年高考成绩查询梧州市,2021年梧州高考状元是谁分数多少分,历年梧州高考状元名单...
- Winxp系统文件夹完全解析
- 译文 | 通俗易懂的机器学习(1)
- mysql在子查询中使用自定义变量和条件语句实现函数效果的查询语句
- OpenGL 亮度调节
- 管理QQ群,什么情况下适合用软件
- uafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in main.obj
- matlab imagesc