IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 11.Linux Linux系统和HelloWorld -> 正文阅读

[系统运维]11.Linux Linux系统和HelloWorld

三个问题

了解Hello World程序的执行过程有什么用?

1.对我们以后开发其他程序有很好的借鉴意义

2.对程序的各种报错有清晰的了解,从而针对性的解决问题

裸机开发中的HelloWorld程序是怎么执行的?

预编译--编译--汇编--连接?

?

Linux系统下的Hello World程序是怎么执行的?

GCC和Hello World

本章以Linux下使用GCC编译Hello World程序来讲解Linux C编程的相关流程和概念。

在Windows下开发C程序代码可以用Visual Studio,开发MCU的程序可以使用Keil、IAR等IDE集成开发环境;而在Linux下也有类似的IDE,如eclipse、Clion等。在这些环境下开发通常我们按照它们预定的步骤建立工程模板,再编写具体的代码,直接点击对应的编译、运行按钮即可完成操作。

在开发大型应用程序特别是调试的时候,使用IDE是非常好的选择, IDE的一个特点是它把各种常用操作封装成图形界面供用户使用,但如同学习Shell命令行的原因一样,在图形界面之下还潜藏着海量的功能,在Linux下的日常开发中常常直接使用命令行来操作,编译时配合其它命令行工具的时候简单快捷,而且非常直观,有利于了解编译的原理。

本章通过解构hello world程序在Linux下的编译运行过程, 掌握GCC、readelf、ldd工具的基本使用,便于理解开发流程以及后期建立编译工具链是要做什么事情。 了解各编译步骤及其生成的文件,这对后期编写Makefile及使用其它工具大有好处。 了解程序的链接过程有利于明白为什么某些程序需要 依赖特定的文件,从而方便专门定制Linux文件系统。

3.1.?GCC编译工具链

GCC编译工具链(toolchain)是指以GCC编译器为核心的一整套工具,用于把源代码转化成可执行应用程序。它主要包含以下三部分内容:

  • gcc-core:即GCC编译器,用于完成预处理和编译过程,例如把C代码转换成汇编代码。

  • Binutils :除GCC编译器外的一系列小工具包括了链接器ld,汇编器as、目标文件格式查看器readelf等。

  • glibc:包含了主要的 C语言标准函数库,C语言中常常使用的打印函数printf、malloc函数就在glibc 库中。

在很多场合下会直接用GCC编译器来指代整套GCC编译工具链。

3.1.1.?GCC编译器

GCC(GNU Compiler Collection)是由 GNU 开发的编程语言编译器。 GCC最初代表“GNU C Compiler”,当时只支持C语言。 后来又扩展能够支持更多编程语言,包括 C++、Fortran 和 Java 等。 因此,GCC也被重新定义为“GNU Compiler Collection”,成为历史上最优秀的编译器, 其执行效率与一般的编译器相比平均效率要高 20%~30%。

GCC的官网地址为:GCC, the GNU Compiler Collection- GNU Project,在Ubuntu系统下系统默认已经安装好GCC编译器,可以通过如下命令查看Ubuntu系统中GCC编译器的版本及安装路径:

#在主机上执行如下命令
gcc -v          #查看gcc编译器版本
which gcc       #查看gcc的安装路径

3.4.?GCC编译过程

3.4.1.?基本语法

GCC使用的命令语法如下:

gcc [选项] 输入的文件名

常用选项:

  • -o:小写字母“o”,指定生成的可执行文件的名字,不指定的话生成的可执行文件名为a.out。

  • -E:只进行预处理,既不编译,也不汇编。

  • -S:只编译,不汇编。

  • -c:编译并汇编,但不进行链接。

  • -g:生成的可执行文件带调试信息,方便使用gdb进行调试。

  • -Ox:大写字母“O”加数字,设置程序的优化等级,如“-O0”“-O1” “-O2” “-O3”, 数字越大代码的优化等级越高,编译出来的程序一般会越小,但有可能会导致程序不正常运行。

3.4.1.1.?编译过程

若不了解程序的编译过程,那么GCC的编译选项会让人一头雾水。下面以X86_64平台下Ubuntu的编译过程为例进行初步讲解, ARM平台下Debian的编译过程也是类似的,不再进行分析。

GCC编译选项除了-g和-Ox选项,其它选项实际上都是编译的分步骤,即只进行某些编译过程。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#直接编译成可执行文件
gcc hello.c -o hello

#以上命令等价于执行以下全部操作
#预处理,可理解为把头文件的代码汇总成C代码,把*.c转换得到*.i文件
gcc –E hello.c –o hello.i

#编译,可理解为把C代码转换为汇编代码,把*.i转换得到*.s文件
gcc –S hello.i –o hello.s

#汇编,可理解为把汇编代码转换为机器码,把*.s转换得到*.o,即目标文件
gcc –c hello.s –o hello.o

#链接,把不同文件之间的调用关系链接起来,把一个或多个*.o转换成最终的可执行文件
gcc hello.o –o hello

对于有MCU开发经验的读者,建议学习一下野火的《STM32库开发实战指南》、《i.MX RT库开发实战指南》中《MDK的编译过程及文件详解》章节,它从MCU的角度非常详细地讲解了上述编译过程。GCC的编译过程也是一样的,而且在Linux平台下解构这个过程更加直观,不过本章作为入门章节,仅从表面去建立编译原理的轮廓,不作深入介绍。

GCC 编译工具链在编译一个C源文件时需要经过以下 4 步:

  1. 预处理,在预处理过程中,对源代码文件中的文件包含(include)、 预编译语句(如宏定义define等)进行展开,生成.i文件。 可理解为把头文件的代码、宏之类的内容转换成更纯粹的C代码,不过生成的文件以.i为后缀。

  2. 编译,把预处理后的.i文件通过编译成为汇编语言,生成.s文件,即把代码从C语言转换成汇编语言,这是GCC编译器完成的工作。

  3. 汇编,将汇编语言文件经过汇编,生成目标文件.o文件,每一个源文件都对应一个目标文件。即把汇编语言的代码转换成机器码,这是as汇编器完成的工作。

  4. 链接,最后将每个源文件对应的.o文件链接起来,就生成一个可执行程序文件,这是链接器ld完成的工作。

四个案例

?gcc预处理c文件

?#预处理,可理解为把头文件的代码汇总成C代码,把*.c转换得到*.i文件

查看打印信息(-v)

sudo gcc -E hello.c -o hello.i -v


COLLECT_GCC_OPTIONS='-E' '-o' 'hello.i' '-v' '-mtune=generic' '-march=x86-64'
?/usr/lib/gcc/x86_64-linux-gnu/7/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu hello.c -o hello.i -mtune=generic -march=x86-64 -fstack-protector-strong -Wformat -Wformat-security
?

?gcc编译c文件

sudo gcc -S hello.i -o hello.s -v

COLLECT_GCC_OPTIONS='-S' '-o' 'hello.s' '-v' '-mtune=generic' '-march=x86-64'
?/usr/lib/gcc/x86_64-linux-gnu/7/cc1 -fpreprocessed hello.i -quiet -dumpbase hello.i -mtune=generic -march=x86-64 -auxbase-strip hello.s -version -o hello.s -fstack-protector-strong -Wformat -Wformat-security
生成汇编文件

?gcc编译汇编

sudo gcc -c hello.s -o hello.o -v

?as -v --64 -o hello.o hello.s
?

?gcc链接可重定位文件

?sudo gcc hello.o -o hello -v

ld连接器

collter2封装了id连接器

/usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJYPevg.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker?(说明编译是动态编译的)/lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o hello /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. hello.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
COLLECT_GCC_OPTIONS='-o' 'hello' '-v' '-mtune=generic' '-march=x86-64'
接下来给大家看一下静态编译

sudo gcc hello.o -o hello_static -v -static

/usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper -plugin-opt=-fresolution=/tmp/ccvPgTQK.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc --build-id -m elf_x86_64 --hash-style=gnu --as-needed -static -z relro -o hello_static /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginT.o -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. hello.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-linux-gnu/7/crtend.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
COLLECT_GCC_OPTIONS='-o' 'hello_static' '-v' '-static' '-mtune=generic' '-march=x86-64'

动态编译出来的hello:8.3k

静态编译出来的hello_static:845k?

sudo gcc hello.c -o hello -v

/usr/lib/gcc/x86_64-linux-gnu/7/cc1 -quiet -v -imultiarch x86_64-linux-gnu hello.c -quiet -dumpbase hello.c -mtune=generic -march=x86-64 -auxbase hello -version -fstack-protector-strong -Wformat -Wformat-security -o /tmp/ccOeHSOm.s
GNU C11 (Ubuntu 7.5.0-3ubuntu1~18.04) version 7.5.0 (x86_64-linux-gnu)
?? ?compiled by GNU C version 7.5.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP
?

as汇编器

?as -v --64 -o /tmp/cc3ne0Az.o /tmp/ccOeHSOm.s
GNU assembler version 2.30 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.30
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-o' 'hello' '-v' '-mtune=generic' '-march=x86-64'
?

先了解到这里吧我睡觉了-_-

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 14:29:21  更:2021-09-27 14:30:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:28:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码