嵌入式C语言(十)

内建函数

这篇我们来看看什么是内建函数欸?

什么是内建函数

内建函数,顾名思义,就是编译器内部实现的函数。**这些函数和关键字一样,可以直接调用,**无须像标准库函数那样,要先声明后使用。

**内建函数的函数命名,通常以__builtin开头。**这些函数主要在编译器内部使用,主要是为编译器服务的。内建函数的主要用途如下。

● 用来处理变长参数列表。

● 用来处理程序运行异常、编译优化、性能优化。

● 查看函数运行时的底层信息、堆栈信息等。

● 实现C标准库的常用函数。

因为内建函数是在编译器内部定义的,主要供与编译器相关的工具和程序调用,所以这些函数并没有文档说明,而且变动又频繁,对于应用程序开发者来说,不建议使用这些函数。

但有些函数,对于我们了解程序运行的底层机制、编译优化很有帮助,在Linux内核中也经常使用这些函数,所以我们很有必要了解Linux内核中常用的一些内建函数。

常用的内建函数

·常用的内建函数主要有两个:__builtin_return_address()和__builtin_frame_address()。

__builtin_return_address(LEVEL)

这个函数用来返回当前函数或调用者的返回地址。函数的参数LEVEL表示函数调用链中不同层级的函数。

● 0:获取当前函数的返回地址。

● 1:获取上一级函数的返回地址。

● 2:获取上二级函数的返回地址。

● ……

整个栗子看看
在这里插入图片描述
在这里插入图片描述

__builtin_frame_address(LEVEL)

在这个之前需要知道栈帧这个概念:
函数每调用一次,都会将当前函数的现场(返回地址、寄存器、临时变量等)保存在栈中,每一层函数调用都会将各自的现场信息保存在各自的栈中。

这个栈就是当前函数的栈帧,每一个栈帧都有起始地址和结束地址,多层函数调用就会有多个栈帧,每个栈帧都会保存上一层栈帧的起始地址,这样各个栈帧就形成了一个调用链。

很多调试器其实都是通过回溯函数的栈帧调用链来获取函数底层的各种信息的,如返回地址、调用关系等。

在ARM处理器平台下,一般使用FP和SP这两个寄存器,分别指向当前函数栈帧的起始地址和结束地址。

当函数继续调用其他函数,或运行结束返回上一级函数时,这两个寄存器的值也会发生变化,总是指向当前函数栈帧的起始地址和结束地址。

我们可以通过内建函数__builtin_frame_address(LEVEL)查看函数的栈帧地址。

● 0:查看当前函数的栈帧地址。

● 1:查看上一级函数的栈帧地址。

● ……

在这里插入图片描述
在这里插入图片描述

C标准库的内建函数

在GNU C编译器内部,C标准库的内建函数实现了一些与C标准库函数类似的内建函数。

这些函数与C标准库函数功能相似,函数名也相同,只是在前面加了一个前缀__builtin。

如果你不想使用C标准库函数,也可以加一个前缀,直接使用对应的内建函数。

常见的C标准库函数如下:

● 与内存相关的函数:memcpy()、memset()、memcmp()。

● 数学函数:log()、cos()、abs()、exp()。

● 字符串处理函数:strcat()、strcmp()、strcpy()、strlen()。

● 打印函数:printf()、scanf()、putchar()、puts()。

下面我们写一个小程序,使用与C标准库对应的内建函数。

在这里插入图片描述
编译程序并运行,程序运行结果如下。

在这里插入图片描述
使用与C标准库对应的内建函数,同样能实现字符串的复制和打印,实现C标准库函数的功能。

内建函数:__builtin_constant_p(n)

编译器内部还有一些内建函数主要用来编译优化、性能优化。

__builtin_constant_p(n) 函数

该函数主要用来判断参数n在编译时是否为常量。如果是常量,则函数返回1,否则函数返回0。

该函数常用于宏定义中,用来编译优化。一个宏定义,根据宏的参数是常量还是变量,可能实现的方法不一样。

来看看内核源码中的花里胡哨的宏:

在这里插入图片描述
在这里插入图片描述
很多宏的操作在参数为常数时可能有更优化的实现,在这个宏定义中,我们实现了2个版本。
根据参数是否为常数,我们可以灵活选用不同的版本。

内建函数:__builtin_expect(exp,c)

内建函数__builtin_expect()也常常用来编译优化,这个函数有2个参数,返回值就是其中一个参数,仍是exp。

这个函数的意义主要是告诉编译器:参数exp的值为c的可能性很大,然后编译器可以根据这个提示信息,做一些分支预测上的代码优化。

参数c与这个函数的返回值无关,无论c为何值,函数的返回值都是exp。

在这里插入图片描述
在这里插入图片描述
这个函数的主要用途是编译器的分支预测优化。

现在CPU内部都有Cache缓存器件。CPU的运行速度很高,而外部RAM的速度相对来说就低了不少,所以当CPU从内存RAM读写数据时就会有一定的性能瓶颈。为了提高程序执行效率,CPU一般都会通过Cache这个CPU内部缓冲区来缓存一定的指令或数据,当CPU读写内存数据时,会先到Cache看看能否找到:如果找到就直接进行读写;如果找不到,则Cache会重新缓存一部分数据进来。CPU读写Cache的速度远远大于内存RAM,所以通过这种缓存方式可以提高系统的性能。

那么Cache如何缓存内存数据呢? **简单来说,就是依据空间相近原则。**如CPU正在执行一条指令,那么在下一个时钟周期里,CPU一般会大概率执行当前指令的下一条指令。如果此时Cache将下面的几条指令都缓存到Cache里,则下一个时钟周期里,CPU就可以直接到Cache里取指、译指和执行,从而使运算效率大大提高。

但有时候也会出现意外。如程序在执行过程中遇到函数调用、if分支、goto跳转等程序结构,会跳到其他地方执行,原先缓存到Cache里的指令不是CPU要执行的指令。此时,我们就说Cache没有命中,Cache会重新缓存正确的指令代码供CPU读取,这就是Cache工作的基本流程。

**有了这些理论基础,我们在编写程序时,遇到if/switch这种选择分支的程序结构,一般建议将大概率发生的分支写在前面。**当程序运行时,因为大概率发生,所以大部分时间就不需要跳转,程序就相当于一个顺序结构,Cache的缓存命中率也会大大提升。

内核中已经实现一些相关的宏,如likely和unlikely,用来提醒程序员优化程序。

Linux内核中的likely和unlikely

在Linux内核中,使用__builtin_expect()内建函数,定义了两个宏。

#define likely(x) __builtin_expect(!!(x),1);
#define unlikely(x) __builtin_expect(!!(x),0);

这两个宏的主要作用:告诉编译器某一个分支发生的概率很高,或者很低,基本不可能发生。编译器根据这个提示信息,在编译程序时就会做一些分支预测上的优化。

在这两个宏的定义中有一个细节,就是对宏的参数x做两次取非操作,这是为了将参数x转换为布尔类型,然后与1和0直接做比较,告诉编译器x为真或假的可能性很高。

在Linux内核源码中,你会发现很多地方使用likely和unlikely宏进行修饰。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/282081.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT是什么,怎么使用,需要注意些什么?

一、ChatGPT 是什么? ChatGPT,全称聊天生成预训练转换器(Chat Generative Pre-trained Transformer),是 OpenAI 开发的人工智能(AI)聊天机器人程序,于2022年11月推出。该程序使用基于GPT-3.5、GPT-4架构的…

权限管理系统-0.6.0

七、员工端审批 员工端审批的大致流程如下图: 这个模块目的是实现员工在微信端的审批提交和处理功能,为了与之前的管理系统区分开,新建一个controller完成这些功能。 7.1 查询审批分类和审批模板 7.1.1 后端接口 //controller Api(tags …

elementUI Tree 树形控件单选实现

文章目录 展示效果代码实现elementui Tree树形控件其他详细数据 在Element UI中,树形控件(el-tree)本身不支持单选功能。但是,你可以通过监听节点点击事件并手动更新选中状态来实现单选树。 以下是一个简单的例子,展示…

【Spring 篇】SpringMVC拦截器:给你的应用增添色彩

嗨,亲爱的小伙伴们!欢迎来到这段关于SpringMVC拦截器的奇妙之旅。今天我们要一探究竟,深入挖掘拦截器的神秘面纱,看看它是如何在你的应用中悄然发挥作用的。别怕,我会用最通俗易懂的语言,一步一步带你走进这…

【合合TextIn】深度解析智能文档处理技术与应用

目录 一、智能文档处理介绍 二、文档格式解析 三、图像增强技术解析 四、传统文字识别OCR技术解析 五、深度学习OCR技术解析 六、深度学习版面分析技术解析 七、文档分类 八、信息抽取 九、系统集成:将IDP处理后的数据集成到企业系统 结论 一、智能文档处…

下载 macOS 系统安装程序的方法

阅读信息: 版本:0.4.20231021 难度:1/10 到 4/10 阅读时间:5 分钟 适合操作系统:10.13, 10.14, 10.15, 11.x, 12.x,13.x, 14 更新2023-10-21 添加Mist的介绍支持版本的更新,13.x&#xff0…

Css提高——Css3的新增选择器

目录 1、Css3新增选择器列举 2、属性选择器 2.1、语法 2.2、代码: 2.3、效果图 3、结构伪类选择器 3.1、语法 3.2、代码 3.3、效果图 3.4、nth:child(n)的用法拓展 nth-child(n)与nth-of-type&#x…

MAC 帧(数据链路层)

目录 一、MAC帧的格式 二、无效的帧 三、帧间最小间隔 四、帧的发送与接收 五、小结 一、MAC帧的格式 • 常用的以太网 MAC 帧格式有两种标准 : DIX Ethernet V2 标准; IEEE 的 802.3 标准。 • 最常用的 MAC 帧是以太网 V2 的格式。 二、…

excel文件可以转成word文件吗?汇帮PDF转换器帮你实现excel转word

将Excel文件转换为Word文档是一个相对简单的任务,但在执行过程中需要注意一些细节,以确保转换后的文档格式正确、内容清晰。下面将详细介绍用汇帮PDF转换器将Excel转Word的步骤和注意事项。 一、Excel文件准备 在进行转换之前,首先确保Excel…

Linux部署MySQL

Linux部署MySQL5.7.17 mkdir /opt/mysql cd /opt/mysql#mysql下载官网: #https://downloads.mysql.com/archives/community/ #下载server、client、lib和common wget https://downloads.mysql.com/archives/get/p/23/file/mysql-community-server-5.7.17-1.el7.…

做抖店不知道怎么找达人?聊聊我是怎么找达人带货的,多看多做!

大家好,我是电商花花。 找不到合适的达人带货?不知道怎么找达人带货?多半都是没有用心去找达人带货,因为现在抖音上遍地都是达人,遍地都是达人在直播带货,在短视频带货。 而达人不是说不缺品,…

刚进公司第一天-电脑环境搭建

写在前面 之前在公司做过一次开发小工具的分享,这两天有个同事找我学习一些小工具开发的知识,但是我发现他的基础是真的差,想学开发知识却连自己本地电脑环境都没弄好,确实,有些人工作了很久,由于自己工作中…

了解Kafka位移自动提交的秘密:避免常见陷阱的方法

欢迎来到我的博客,代码的世界里,每一行都是一个故事 了解Kafka位移自动提交的秘密:避免常见陷阱的方法 前言位移自动提交简介自动提交的优缺点自动提交位移的优点:自动提交位移的缺点:自动提交与手动提交的对比分析&am…

【ScienceAI Weekly】「AI钢铁侠」黄仁勋在GTC大会聊英伟达布局科研;Overjet获牙科AI历史最大投资

AI for Science 的新成果、新动态、新视角—— 英伟达:有众多 AI for Scinece 领域的战略内容在布局 微软携手多家医疗机构推出 TRAIN Overjet 获牙科 AI 历史上最大的投资 联想控股与智谱 AI在生物科技等领域达成合作 Zephyr AI 获得 1.11 亿美元 A 轮融资 中…

扩容分区和文件系统(Linux)

在ECS控制台上扩容云盘容量后,对应分区和文件系统并未扩容,您还需要进入ECS实例内部继续扩容云盘的分区和文件系统,将扩容部分的容量划分至已有分区及文件系统内,使云盘扩容生效。本文为您介绍如何通过两个步骤完成Linux实例云盘的…

在线播放视频网站源码系统 带完整的安装代码包以及搭建教程

在线播放视频网站源码系统的开发,源于对当前视频市场的深入洞察和用户需求的精准把握。随着视频内容的爆炸式增长,用户对视频播放的需求也日益多样化。他们希望能够随时随地观看自己感兴趣的视频内容,同时还希望能够在观看过程中享受到流畅、…

【Frida】10_用鼠标自动标记棋盘上的雷区(一键过关)

🛫 系列文章导航 【Frida】 00_简单介绍和使用 https://blog.csdn.net/kinghzking/article/details/123225580【Frida】 01_食用指南 https://blog.csdn.net/kinghzking/article/details/126849567【Frida】02_常见API示例及功能函数封装(snippets&#…

Go 1.22 - 更加强大的 Go 执行跟踪

原文:Michael Knyszek - 2024.03.14 runtime/trace 包含了一款强大的工具,用于理解和排查 Go 程序。这个功能可以生成一段时间内每个 goroutine 的执行追踪。然后,你可以使用 go tool trace 命令(或者优秀的开源工具 gotraceui&a…

【Java - 框架 - Knife4j】(01) SpringBoot整合Knife4j - 快速上手

“SpringBoot"整合"Knife4j” - 快速上手; 环境 “Knife4j"版本"2.0.9”;“Java"版本"1.8.0_202”;“Spring Boot"版本"2.5.9”;“Windows 11 专业版_22621.2428”;“Intel…

GPT-5可能会在今年夏天作为对ChatGPT的“实质性改进”而到来

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…