__attribute__((__used__)) 和 __attribute__((__section__(“*“ “*“)))的使用

见:haproxy代码

C语言注册函数和调用函数,便于模块化开发和编程。

#include <stdio.h>

#ifdef __APPLE__
#define HA_SECTION(s)           __attribute__((__section__("__DATA, " s)))
#define HA_SECTION_START(s)     __asm("section$start$__DATA$" s)
#define HA_SECTION_STOP(s)      __asm("section$end$__DATA$" s)
#else
#define HA_SECTION(s)           __attribute__((__section__(s)))
#define HA_SECTION_START(s)
#define HA_SECTION_STOP(s)
#endif

/*
 * Please keep those names short enough, they are used to generate section
 * names, Mac OS X accepts section names up to 16 characters, and we prefix
 * them with i_, so stage name can't be more than 14 characters.
 */
enum init_stage {
	STG_PREPARE = 0,      // preset variables, tables, list heads
	STG_LOCK,             // pre-initialize locks
	STG_REGISTER,         // register static lists (keywords etc)
	STG_ALLOC,            // allocate required structures
	STG_POOL,             // create pools
	STG_INIT,             // subsystems normal initialization
	STG_SIZE              // size of the stages array, must be last
};

/* This is the descriptor for an initcall */
struct initcall {
	void (*const fct)(void *arg1, void *arg2, void *arg3);
	void *arg1;
	void *arg2;
	void *arg3;
#if defined(USE_OBSOLETE_LINKER)
	void *next;
#endif
};

/* declare a symbol as global */
#define __HA_GLOBL(sym)   __asm__(".globl " #sym)
#define HA_GLOBL(sym)     __HA_GLOBL(sym)

#define HA_INIT_SECTION(s)  HA_SECTION("i_" # s)

#define __DECLARE_INITCALL(stg, linenum, function, a1, a2, a3)     \
        HA_GLOBL(__start_i_##stg );                                \
        HA_GLOBL(__stop_i_##stg );                                 \
	static const struct initcall *__initcb_##linenum           \
	    __attribute__((__used__)) HA_INIT_SECTION(stg) =	   \
	        (stg < STG_SIZE) ? &(const struct initcall) {      \
		.fct = (void (*)(void *,void *,void *))function,   \
		.arg1 = (void *)(a1),                              \
		.arg2 = (void *)(a2),                              \
		.arg3 = (void *)(a3),                              \
	} : NULL

#define _DECLARE_INITCALL(...) \
	__DECLARE_INITCALL(__VA_ARGS__)

#define INITCALL0(stage, function)  \
	_DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)

/* Declare func */
#define DECLARE_INIT_SECTION(stg)                                                   \
	extern __attribute__((__weak__)) const struct initcall *__start_i_##stg HA_SECTION_START("i_" # stg); \
	extern __attribute__((__weak__)) const struct initcall *__stop_i_##stg  HA_SECTION_STOP("i_" # stg)

#define FOREACH_INITCALL(p,stg)                                               \
	for ((p) = &(__start_i_##stg); (p) < &(__stop_i_##stg); (p)++)

#define RUN_INITCALLS(stg)                                                     \
	do {                                                                   \
		const struct initcall **ptr;                                   \
		if (stg >= STG_SIZE)                                           \
			break;                                                 \
		FOREACH_INITCALL(ptr, stg)                                     \
			(*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
	} while (0)

/* register func1 */
static void _do_register_func1(void)
{
    printf("TEST: _do_register_func1()\n");
}
#if 0
__asm__(".globl " "__start_i_STG_REGISTER"); 
__asm__(".globl " "__stop_i_STG_REGISTER"); 
static const struct initcall *__initcb_405 __attribute__((__used__)) __attribute__((__section__("i_" "STG_REGISTER"))) = (STG_REGISTER < STG_SIZE) ? &(const struct initcall) 
{ 
    .fct = (void (*)(void *,void *,void *))_do_register, 
    .arg1 = (void *)(0), 
    .arg2 = (void *)(0), 
    .arg3 = (void *)(0), 
} : ((void *)0);
#endif
INITCALL0(STG_REGISTER, _do_register_func1);

/* register func2 */
static void _do_register_func2(void)
{
    printf("TEST: _do_register_func2()\n");
}
INITCALL0(STG_REGISTER, _do_register_func2);

/* register func3 */
static void _do_register_func3(void)
{
    printf("TEST: _do_register_func3()\n");
}
INITCALL0(STG_REGISTER, _do_register_func3);

/* declare func1, func2, func3 */
DECLARE_INIT_SECTION(STG_REGISTER);

int main(int argc, char *const argv[])
{
    /* call func1, func2, func3 */
    RUN_INITCALLS(STG_REGISTER);

    printf("hello world\n");
    return 0;
}

编译和运行:

ubuntu@dev:test-06$ gcc test1.c
ubuntu@dev:test-06$ ./a.out 
TEST: _do_register_func1()
TEST: _do_register_func2()
TEST: _do_register_func3()
hello world

不使用__attribute__((used)) 和 attribute((section(““ ““)))

#include <stdio.h>

/* register func1 */
static void _do_register_func1(void)
{
    printf("TEST: _do_register_func1()\n");
}

/* register func2 */
static void _do_register_func2(void)
{
    printf("TEST: _do_register_func2()\n");
}

/* register func3 */
static void _do_register_func3(void)
{
    printf("TEST: _do_register_func3()\n");
}

int main(int argc, char *const argv[])
{
    /* call func1, func2, func3 */
    _do_register_func1();
    _do_register_func2();
    _do_register_func3();

    printf("hello world\n");
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux内的循环

格式 while 【 条件判断 】 do 语句体 done 上图 第一次代码&#xff0c;输入语句在外面&#xff0c;结果输入完&#xff08;非hello&#xff09;程序不断循环&#xff0c;没办法&#xff0c;ctrlc给程序终止了&#xff0c;然后把用户输入的语句放到了循环体里面…

vivo发布“蓝心千询”自然语言对话机器人

&#x1f989; AI新闻 &#x1f680; vivo发布“蓝心千询”自然语言对话机器人 摘要&#xff1a;vivo今日发布了“蓝心千询”自然语言对话机器人&#xff0c;基于蓝心大模型。蓝心千询可以进行知识信息的快速问答&#xff0c;文学创作、图片生成&#xff0c;甚至还能编写程序…

SAM 微调在医学上的尝试

1、2023下半年 1、 UNet与SAM结合的正确的道路SAMUS,一路SOTA没对手&#xff01; https://github.com/xianlin7/SAMUS 2、 本文提出 SonoSAM&#xff1a;一种用于分割超声图像上感兴趣对象的快速基础模型。 https://zhuanlan.zhihu.com/p/663988684 未开源 绿色是预测的&…

流媒体服务实现H5实时预览视频

目录 背景方案业务实践细节注意 待办 背景 客户aws服务磁盘存储告急&#xff0c;最高可扩容16T。排查如下&#xff1a;主要是视频文件存在大量复制使用的情况。例如发布节目时复制、预览时复制&#xff0c;这样上传一份视频后最大会有四份拷贝&#xff08;预览、普通发布、互动…

http中的Content-Type类型

浏览器的Content-Type 最近在做web端下载的时候需要给前端返回一个二进制的流&#xff0c;需要在请求头中设置一个 writer.Header().Set("Content-Type", "application/octet-stream")那么http中的Content-Type有具体有哪些呢&#xff1f;他们具体的使用场…

作用域,基本数据类型(常量const),转义字符,运算符

1.作用域 全局作用域&#xff1a;定义在所有花括号外的名字具有“全局作用域” 块作用域&#xff1a;在某个花括号内定义的名字具有“块作用域” 一般把具有全局作用域的变量叫做“全局变量”&#xff0c;具有块作用域的变量叫做“局部变量” 如果在嵌套作用域里出现重名&a…

Linux进程的优先级

Linux进程的优先级 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容讲解Linux中进程的优先级&#xff0…

视频集中存储/云存储EasyCVR启动后查询端口是否被占用出错,该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

LINQ to SQL系列三 使用DeferredLoadingEnabled,DataLoadOption指定加载选项

介绍linq to sql 的 DataContext类DeferredLoadingEnabled属性使用,以及DataLoadOptions限定加载相关表数据的LoadWith和AssociateWith方法。 本文中举例用到的数据模型如下: Student和Class之间是多对一关系,Student和Course之间是多对多关系。 DataContext的DeferredLo…

策略模式在数据接收和发送场景的应用

在本篇文章中&#xff0c;我们介绍了策略模式&#xff0c;并在数据接收和发送场景中使用了策略模式。 背景 在最近项目中&#xff0c;需要与外部系统进行数据交互&#xff0c;刚开始交互的系统较为单一&#xff0c;刚开始设计方案时打算使用了if else 进行判断&#xff1a; if(…

宝塔面板使用Supervisor进程守护插件,配置守护Mysql的操作教程。

本篇文章主要讲解&#xff0c;在宝塔面板中使用Supervisor进程守护插件&#xff0c;配置守护Mysql的操作教程。 作者&#xff1a;任聪聪 日期&#xff1a;2023年11月5日 一、安装守护进程插件 安装插件一、进程守护插件 安装说明&#xff1a;在软件商店中搜索“进程守护”&am…

elasticsearch下载和安装(linux)看这一篇就够了

配置java环境&#xff08;11版本以上&#xff09; 1.下载安装包 我是放在usr下的java里了 2.解压 tar -zxvf jdk-17_linux-x64_bin.tar.gz3.配置环境变量 vim /etc/profile在文件的最下面添加 JAVA_HOME/usr/java/jdk-17.0.9 #你自己的安装路径 JRE_HOME$JAVA_HOME/jre C…

项目实战:组件扫描实现(1)-扫描类路径所有文件

1、ComponentScan 组件扫描类 一下知识本人都是在Maven工程下总结的&#xff0c;所以目录结构会不一样这个类的作用是扫描所有的classes目录下的所有的字节码文件&#xff0c;找到相应的类&#xff0c;然后找到相应类上的注解 package com.csdn.mymvc.core; import java.io.Fi…

6.数据类型与运算符

目录 mysql数据类型 整型数据类型 浮点数类型和定点数类型 1、日期时间类型 1、YEAR 2、TIME 3、DATE类型 4、DATETIME 5、TIMESTAMP 2、字符串类型 1、CHAR 和 VARCHAR类型&#xff1a; 2、TEXT类型 3、ENUM类型 4、SET类型 二进制字符串类型 1、BIT类型 2、…

链表面试OJ题(1)

今天讲解两道链表OJ题目。 1.链表的中间节点 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&#xff1a;链表只有一个…

iOS17.2正式版什么时候发布? 13大新功能细节抢先看

苹果已经发布了针对开发者的iOS 17.2 Beta测试版&#xff0c;而iOS 17.2正式版预计会在2023年12月发&#xff0c;新版本给iPhone带来不少新功能&#xff0c;下面小编就带大家抢先了解iOS 17.2即将带来的13个新功能亮点细节。 1.手记Journal App上线 全新「手记」 Journal App终…

访问控制、RBAC和ABAC模型

访问控制、RBAC和ABAC模型 访问控制 访问控制的目的是保护对象&#xff08;数据、服务、可执行应用该程序、网络设备或其他类型的信息技术&#xff09;不受未经授权的操作的影响。操作包括&#xff1a;发现、读取、创建、编辑、删除和执行等。 为实现访问控制&#xff0c; 计…

使用cpolar配合Plex搭建私人媒体站并实现远程访问

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频&#xff0c;已经算是生活中稀松平常的场景了&#xff0c;特别是各…

软件开发项目文档系列之十如何撰写测试用例

目录 1 概述1.1 编写目的1.2 定义1.3 使用范围1.4 参考资料1.5 术语定义 2 测试用例2.1 功能测试2.1.1 用户登录功能2.1.2 商品搜索功能 2.2 性能测试2.2.1 网站响应时间2.2.2 并发用户测试 附件&#xff1a; 测试用例撰写的要素和注意事项附件1 测试用例要素附件2 测试用例的注…

el-input输入校验插件(正则表达式)

使用方法&#xff1a;在main.js文件中注册插件然后直接在<el-input>加入‘v-插件名’ (1)在main.js文件&#xff1a; // 只能输入数字指令 import onlyNumber from /directive/only-number; Vue.use(onlyNumber); &#xff08;2&#xff09;在src/directive文件夹中 &a…
最新文章