【Make编译控制 01】程序编译与执行
目录
一、编译原理概述
二、编译过程分析
三、编译动静态库
四、执行过程分析
一、编译原理概述
make: 一个GCC工具程序,它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接,然后发布必要的命令。它读出的脚本(叫做 makefile 或 Makefile)定义了文件关系和依赖关系。
# 查看GCC默认头文件搜索路径echo | gcc -v -x c -E -
#include <stdio.h>int main()
{printf("hello, world\n");return 0;
}
hello 程序的生命周期是从一个源程序(或者说源文件)开始的,即程序员通过编辑器创建并保存的文本文件,文件名是 hello.c。源程序实际上就是一个由值 0 和 1组成的位(又称为比特)序列,8 个位被组织成一组,称为字节。每个字节表示程序中的某些文本字符。
大部分计算机使用 ASCII 标准来表示文本字符:
- 用一个唯一的单字节大小的整数值息来表示每个字符
- hello.c 程序是以字节序列的方式储存在文件中的
hello.c 的表示方法说明了一个基本思想:系统中所有的信息——包括磁盘文件、内存中的程序、内存中存放的用户数据以及网络上传送的数据,都是由一串比特表示的。
二、编译过程分析
hello 程序的生命周期从一个高级 C 语言程序开始。
为了在系统上运行 hello.c 程序,每条 C 语句都必须被其他程序转化为一系列的低级机器语言指令。
然后这些指令按照一种称为可执行目标程序的格式打好包,并以二进制磁盘文件的形式存放起来。
GCC 编译器读取源程序文件 hello.c,并把它翻译成一个可执行目标文件 hello。这个翻译过程可分为四个阶段完成,如下图所示:
执行这四个阶段的程序(预处理器、编译器、汇编器和链接器)一起构成了编译系统(compilation system)。
# 预处理 Preprocessing
# -E 选项告诉编译器只进行预处理操作
# -o 选项把预处理的结果输出到指定文件(base) [root@localhost 01_test]# vim hello.c
(base) [root@localhost 01_test]# cat hello.c
#include <stdio.h>int main()
{printf("hello, world\n");return 0;
}
(base) [root@localhost 01_test]# gcc -E hello.c -o hello.i
(base) [root@localhost 01_test]# ls
hello.c hello.i
(base) [root@localhost 01_test]#
# 生成汇编语言 Generating Assembly Language
# -S 选项告诉编译器,进行预处理和编译成汇编语言操作(base) [root@localhost 01_test]# gcc -S hello.i -o hello.s
(base) [root@localhost 01_test]# ls
hello.c hello.i hello.s
(base) [root@localhost 01_test]# cat hello.s.file "hello.c".section .rodata
.LC0:.string "hello, world".text.globl main.type main, @function
main:
.LFB0:.cfi_startprocpushq %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq %rsp, %rbp.cfi_def_cfa_register 6movl $.LC0, %edicall putsmovl $0, %eaxpopq %rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size main, .-main.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)".section .note.GNU-stack,"",@progbits
(base) [root@localhost 01_test]#
# 源程序编译为目标程序 Source File to Object File
# -c 选项告诉编译器,将源代码或汇编代码翻译成二进制机器代码(base) [root@localhost 01_test]# ls
hello.c hello.i hello.s
(base) [root@localhost 01_test]# gcc -c hello.s -o hello.o
(base) [root@localhost 01_test]# ls
hello.c hello.i hello.o hello.s
(base) [root@localhost 01_test]# cat hello.o
ELF>�@@
UH����]�hello, worldGCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)zRx
P A�C
�� hello.cmainputs�������� .symtab.strtab.shstrtab.rela.text.data.bss.rodata.comment.note.GNU-stack.rela.eh_frame @�0
90b.B�W�R@
��0a(base) [root@localhost 01_test]#
# 可执行文件生成 Executable
# -o 选项告诉编译器生成可执行文件(base) [root@localhost 01_test]# ls
hello.c hello.i hello.o hello.s
(base) [root@localhost 01_test]# gcc hello.o -o hello
(base) [root@localhost 01_test]# ls
hello hello.c hello.i hello.o hello.s
(base) [root@localhost 01_test]# ./hello
hello, world
(base) [root@localhost 01_test]#
# 我们也可以直接将源代码生成可执行文件
# 可以单个源文件生成可执行文件,也可以多个源文件生成可执行文件(base) [root@localhost 01_test]# gcc hello.c -o hello
(base) [root@localhost 01_test]# ls
hello hello.c
(base) [root@localhost 01_test]# ./hello
hello, world
(base) [root@localhost 01_test]#
源文件.c文件 -> 预编译成.i文件 -> 编译成汇编语言.s -> 汇编成.o文件 -> 链接成可执行文件。
三、编译动静态库
# 创建一个静态库 Create a Static Lib# 编译成 .o 文件
gcc -c [.c] -o [自定义文件名]
gcc -c [.c] [.c] ...# 编静态库
ar -r [lib自定义库名.a] [.o] [.o] ...# 链接成可执行文件
gcc [.c] [.a] -o [自定义输出文件名]
gcc [.c] -o [自定义输出文件名] -l[库名] -L[库所在路径](base) [root@localhost 02_test]# vim add.c
(base) [root@localhost 02_test]# vim minus.c
(base) [root@localhost 02_test]# cat add.c
int add(int a, int b) {return a + b;
}
(base) [root@localhost 02_test]# cat minus.c
int minus(int a, int b) {return a - b;
}
(base) [root@localhost 02_test]# vim main.c
(base) [root@localhost 02_test]# cat main.c
#include <stdio.h>int add(int a, int b);
int minus(int a, int b);int main() {int a = 10;int b = 5;printf("a + b = %d\n", add(a, b));printf("a - b = %d\n", minus(a, b));return 0;
}
(base) [root@localhost 02_test]# gcc -c add.c -o add.o
(base) [root@localhost 02_test]# gcc -c minus.c -o minus.o
(base) [root@localhost 02_test]# ar -r mymathlib.a add.o minus.o
ar: 正在创建 mymathlib.a
(base) [root@localhost 02_test]# gcc main.c mymathlib.a -o math.exe
(base) [root@localhost 02_test]# ./math.exe
a + b = 15
a - b = 5
(base) [root@localhost 02_test]#
# 创建一个动态库 Create a Shared Lib# 编译成二进制 .o 文件
gcc -c -fpic [.c/.cpp][.c/.cpp]... # 编动态库
gcc -shared [.o][.o]... -o [lib自定义库名.so]# 链接库到可执行文件
gcc [.c/.cpp] -o [自定义可执行文件名] -l[库名] -L[库路径]# 告诉编译器动态库的位置
# 1. 安装,不建议往系统库添加头文件
# 2. 添加环境变量,重启后无效
# 3. 配置 /etc/ld.so.conf.d 文件,永久有效
# 4. 建立软链接,永久有效(base) [root@localhost 02_test]# gcc -c -fpic add.c minus.c
(base) [root@localhost 02_test]# ls
add.c add.o main.c minus.c minus.o
(base) [root@localhost 02_test]# gcc -shared add.o minus.o -o libmymathlib.so
(base) [root@localhost 02_test]# ls
add.c add.o libmymathlib.so main.c minus.c minus.o
(base) [root@localhost 02_test]# gcc main.c -o math -lmymathlib -L.
(base) [root@localhost 02_test]# ls
add.c add.o libmymathlib.so main.c math minus.c minus.o
(base) [root@localhost 02_test]# ./math
./math: error while loading shared libraries: libmymathlib.so: cannot open shared object file: No such file or directory
(base) [root@localhost 02_test]# pwd
/root/gitee/Test/Make_Learn/02_test
(base) [root@localhost 02_test]# rm math
rm:是否删除普通文件 "math"?y
(base) [root@localhost 02_test]# gcc main.c -o math -lmymathlib -L/root/gitee/Test/Make_Learn/02_test
(base) [root@localhost 02_test]# ./math
./math: error while loading shared libraries: libmymathlib.so: cannot open shared object file: No such file or directory
(base) [root@localhost 02_test]# ln -s ./libmymathlib.so /lib64/libmymathlib.so
(base) [root@localhost 02_test]# ./math
./math: error while loading shared libraries: libmymathlib.so: cannot open shared object file: Error 40
(base) [root@localhost 02_test]# pwd
/root/gitee/Test/Make_Learn/02_test
(base) [root@localhost 02_test]# ls /lib64/libmymathlib.so
ls: 无法访问/lib64/libmymathlib.so: 符号连接的层数过多
(base) [root@localhost 02_test]# rm -rf /lib64/libmymathlib.so
(base) [root@localhost 02_test]# ln -s /root/gitee/Test/Make_Learn/02_test/libmymathlib.so /lib64/libmymathlib.so
(base) [root@localhost 02_test]# ./math
a + b = 15
a - b = 5
(base) [root@localhost 02_test]#
四、执行过程分析
第一步:
- shell 等待我们输入一个命令
- 当我们在键盘上输入字符串"./hello"(注意这里是编译好的可执行目标文件)后
- shell 程序将字符逐一读入寄存器
- 再把它存放到内存中
第二步:
- 当我们在键盘上敲回车键时,shell 程序就知道我们已经结束了命令的输人
- 然后 shell 执行一系列指令来加载可执行的 hello 文件
- 这些指令将 hello 目标文件中的代码和数据从磁盘复制到主存
- 数据包括最终会被输出的字符串"hello,world\n"
第三步:
- 一旦目标文件 hello 中的代码和数据被加载到主存
- 处理器就开始执行 hello 程序的 main 程序中的机器语言指令
- 这些指令将 "hello,world\n" 字符串中的字节从主存复制到寄存器文件
- 再从寄存器文件中复制到显示设备,最终显示在屏幕上
相关文章:

【Make编译控制 01】程序编译与执行
目录 一、编译原理概述 二、编译过程分析 三、编译动静态库 四、执行过程分析 一、编译原理概述 make: 一个GCC工具程序,它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接,然后发布必要的命令。它读出的脚本(叫做 …...
MySQL如何定位慢查询
MySQL中定位慢查询通常涉及到以下几个步骤: 1. 慢查询日志 开启慢查询日志是识别慢查询的第一步。通过设置slow_query_log变量为1,MySQL会记录所有执行时间超过long_query_time秒的查询。 -- 开启慢查询日志 SET GLOBAL slow_query_log ON;-- 设置慢…...

npm 上传一个自己的应用(4) 更新自己上传到NPM中的工具版本 并进行内容修改
前面 npm 上传一个自己的应用(2) 创建一个JavaScript函数 并发布到NPM 我们讲了将自己写的一个函数发送到npm上 那么 如果我们想到更好的方案 希望对这个方法进行修改呢? 比如 我们这里加一个方法 首先 我们还是要登录npm npm login然后 根据要求填写 Username 用…...

Linux开发:PAM1 介绍
PAM(Pluggable Authentication Modules )是Linux提供的一种通用的认证方式,他可以根据需要动态的加载认证模块,从而减少认证开发的工作量以及提供认证的灵活度。 1.PAM的框架 PAM的框架由一下几个部分构成 1)应用程序,即需要使用认证服务的程序,这些应用程序是使用抽象…...
Leetcode 3036. Number of Subarrays That Match a Pattern II
Leetcode 3036. Number of Subarrays That Match a Pattern II 1. 解题思路2. 代码实现 3036. Number of Subarrays That Match a Pattern II 1. 解题思路 这一题其实有点水,因为本质上还是一道套路题目,和前两周的两道题目一样,都是考察的…...

华为环网双机接入IPTV网络部署案例
环网双机接入IPTV网络部署案例 组网图形 图2 环网双机场景IPTV基本组网图 方案简介配置注意事项组网需求数据规划配置思路操作步骤配置文件 方案简介 随着IPTV业务的迅速发展,IPTV平台承载的用户也越来越多,用户对IPTV直播业务的可靠性要求越来越高。…...

“智能检测,精准把控。温湿度检测系统,为您的生活带来全方位的健康保障。”#非标协议项目【上】
“智能检测,精准把控。温湿度检测系统,为您的生活带来全方位的健康保障。”#非标协议项目【上】 前言预备知识1温湿度检测系统需求2.代码整合2.1找到编程实现LCD1602显示一行工程,打开代码文件,将所需的LCD1602驱动代码拷贝到温湿…...

牛客网SQL进阶137:第二快/慢用时之差大于试卷时长一半的试卷
官网链接: 第二快慢用时之差大于试卷时长一半的试卷_牛客题霸_牛客网现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别,。题目来自【牛客题霸】https://www.nowcoder.com/practice/b1e2864271c14b63b0df9fc08b559166?tpId240 0 问题描述 试…...

CVE-2022-0760 漏洞复现
CVE-2022-0760 NSS [HNCTF 2022 WEEK2]ohmywordpress 【CVE-2022-0760】 题目描述:flag在数据库里面。 开题: 顺着按钮一直点下去会发现出现一个按钮叫安装WordPress 安装完之后的界面,有一个搜索框。 F12看看network。 又出现了这个Wor…...

WordPress突然后台无法管理问题
登录WordPress后台管理评论,发现点击编辑、回复均无反应。 尝试清除缓存、关闭CF连接均无效。 查看插件时发现关闭wp-china-yes插件可以解决问题。 后来又测试了下发现加速管理后台这项,在启用时会发生点击无效问题,禁用就好了,不…...

STM32F1 - 标准外设库_规范
STM32F10x_StdPeriph_Lib_V3.6.0 1> 头文件包含关系2> .c文件内部结构3> 宏定义位置4> 位掩码bit mask5> .c文件中定义私有变量6> 枚举类型定义 1> 头文件包含关系 1个头文件stm32f10x.h 就把整个MCU以及标准外设库,就管理了; 2>…...

推荐系统|召回04_离散特征处理
离散特征处理 离散特征是什么 怎么处理离散特征 One-hot编码 Embedding嵌入 从one-hot到Embedding,已经节省了很多的存储空间,但当数据量大的时候,还是占空间,所以工业界仍会对Embedding进行优化 而一个物品所对应的Embedding参数…...

一个查看armv8系统寄存器-值-含义的方式
找到解压后的SysReg_xml_v86A-2019-12目录 wget https://developer.arm.com/-/media/developer/products/architecture/armv8-a-architecture/2019-12/SysReg_xml_v86A-2019-12.tar.gz wget https://developer.arm.com/-/media/developer/products/architecture/armv8-a-archi…...

LLMs之miqu-1-70b:miqu-1-70b的简介、安装和使用方法、案例应用之详细攻略
LLMs之miqu-1-70b:miqu-1-70b的简介、安装和使用方法、案例应用之详细攻略 目录 miqu-1-70b的简介 miqu-1-70b的安装和使用方法 1、安装 2、使用方法 miqu-1-70b的案例应用 miqu-1-70b的简介 2024年1月28日,发布了miqu 70b,潜在系列中的…...

npm 下载报错
报错信息 : 证书过期 (CERT_HAS_EXPIRED) D:\Apps\nodejs-v18.16.1\npx.cmd --yes create-next-app"latest" . --ts npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/create-next-app failed…...
GPT-4登场:多模态能力革新,提升ChatGPT与必应体验,开放API助力游戏革新
GPT-4登场:多模态能力革新,提升ChatGPT与必应体验,开放API助力游戏革新 引言 在人工智能领域,GPT-4的发布标志着一个新时代的到来。这一多模态大模型不仅在技术性能上实现了飞跃,更在功能层面带来全新的突破。GPT-4的…...

【芯片设计- RTL 数字逻辑设计入门 11.1 -- 状态机实现 移位运算与乘法 1】
文章目录 移位运算与乘法状态机简介SystemVerilog中的测试平台VCS 波形仿真 阻塞赋值和非阻塞赋值有限状态机(FSM)与无限状态机的区别 本篇文章接着上篇文章【芯片设计- RTL 数字逻辑设计入门 11 – 移位运算与乘法】 继续介绍,这里使用状态机…...
MongoDB系列:管道操作:聚合阶段操作符(二)
MongoDB系列:管道操作:聚合阶段操作符(二) 聚合阶段操作符介绍 本节只编写了个人认为可能用到的操作符,详细更多的操作符以及使用注意事项请前往MongoDB官网。 $match 过滤匹配数据。 // 插入数据 db.orders.inse…...

C++ //练习 5.12 修改统计元音字母的程序,使其能统计以下含有两个字符的字符序列的数量:ff、fl和fi。
C Primer(第5版) 练习 5.12 练习 5.12 修改统计元音字母的程序,使其能统计以下含有两个字符的字符序列的数量:ff、fl和fi。 环境:Linux Ubuntu(云服务器) 工具:vim 代码块 /****…...

C语言-----自定义类型-----结构体枚举联合
结构体和数组一样,都是一群数据的集合,不同的是数组当中的数据是相同的类型,但是结构体中的数据类型可以不相同,结构体里的成员叫做成员变量 结构体类型是C语言里面的一种自定义类型,我们前面已经了解到过int,char,fl…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...

qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...

Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...