0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言中section关键字的作用?其在SDK实现开机自启动的应用?

Dp1040 来源:嵌入式系统 2023-10-08 16:01 次阅读

1、section的作用

section主要作用是将函数或者变量放在指定段中,这样就可在指定的位置取出。

//section demo with gcc
#include"stdio.h"

int__attribute__((section("my_fun")))test1(inta,intb)
{
return(a+b);
}

inttest(intb)
{
return2*b;
}

int__attribute__((section("my_fun")))test0(inta,intb)
{
return(a*b);
}

int__attribute__((section("my_val")))chengi;
int__attribute__((section("my_val")))chengj;

intmain(void)
{
intsum,c,j;
chengi=1,chengj=2;

sum=test1(chengi,chengj);
c=test(100);
j=test0(chengi,chengj);

printf("sum=%d,c=%d,j=%d
",sum,c,j);

return0;
}

编译生成map文件:

gcc-o main.exe main.c-Wl,-Map,my_test.map

my_test.map 文件片段如下:

.text0x004014600xa0C:\Users\think\ccmGLaeH.o
0x00401460test
0x0040146amain

.text0x004015000x0c:/mingw/bin/../libmingw32.a(CRTglob.o)

......
my_fun0x004040000x200
[!provide]PROVIDE(___start_my_fun,.)

my_fun0x004040000x1cC:\Users\think\ccmGLaeH.o

0x00404000test1
0x0040400dtest0

[!provide]PROVIDE(___stop_my_fun,.)

.data0x004050000x200

0x00405000\__data_start_\_=.
......
*(.data_cygwin_nocopy)
my_val0x004060000x200

[!provide]PROVIDE(___start_my_val,.)

my_val0x004060000x8C:\Users\think\ccdMcTrl.o
0x00406000chengi
0x00406004chengj

[!provide]PROVIDE(___stop_my_val,.)

.rdata0x004070000x400

分析可见,使用section修饰的函数和变量在自定义的片段,而且是连续存放在___start_xx到___stop_xx之间,这样可根据变量的地址得出与其同段变量的地址,为后续自动初始化等功能提供了基础。

2、 自动初始化

基于前面section的作用,可以将同类函数指针全部使用同一个段名修饰,然后开机后系统自动检索段内函数指针,逐个执行,对上层应用就是无需主动调用,系统自动初始化。

考虑到硬件初始化与应用功能初始化的先后顺序,可以对段名进行分配,map文件按段名排序。自动初始化主体是OS_INIT_EXPORT宏。

范例代码出自中国移动的oneos开源版本,使用gcc,方案和国产RT-Thread类似。

typedefos_err_t(*os_init_fn_t)(void);

#defineOS_INIT_EXPORT(fn,level)
const os_init_fn_t __os_call_##fn OS_SECTION(".init_call."level)=fn

#defineOS_BOARD_INIT(fn)OS_INIT_EXPORT(fn,"1")

#defineOS_PREV_INIT(fn)OS_INIT_EXPORT(fn,"2")

#defineOS_DEVICE_INIT(fn)OS_INIT_EXPORT(fn,"3")

#defineOS_CMPOENT_INIT(fn)OS_INIT_EXPORT(fn,"4")

#defineOS_ENV_INIT(fn)OS_INIT_EXPORT(fn,"5")

#defineOS_APP_INIT(fn)OS_INIT_EXPORT(fn,"6")

例如shell初始化函数,定义如下:

OS_APP_INIT(sh_system_init);

将宏定义展开:

/*含义是函数指针__os_call_sh_system_init
*其指向sh_system_init函数,且该指针编译后放在".init_call.6"段
*/
constos_init_fn_t__os_call_sh_system_init
__attribute__((section((".init_call.6"))))=sh_system_init

系统自身也有自定义函数,用来标记起止点函数。

OS_INIT_EXPORT(os_init_start,"0");//段起点__start
OS_INIT_EXPORT(os_board_init_start,"0.end");
OS_INIT_EXPORT(os_board_init_end,"1.end");
OS_INIT_EXPORT(os_init_end,"6.end");//段终点__stop

最终生成的map文件,如下图所示:

//系统底层在合适的时机调用如下两函数,将指定段区间内的所有函数自动执行

voidos_board_auto_init(void)
{
constos_init_fn_t*fn_ptr_board_init_start;
constos_init_fn_t*fn_ptr_board_init_end;
constos_init_fn_t*fn_ptr;

fn_ptr_board_init_start=&__os_call_os_board_init_start+1;
fn_ptr_board_init_end=&__os_call_os_board_init_end-1;

//将段首尾区间内的函数全部遍历执行
for(fn_ptr=fn_ptr_board_init_start;fn_ptr<= fn_ptr_board_init_end; fn_ptr++)
    {
        (void)(*fn_ptr)();
    }
    return;
}

static void os_other_auto_init(void)
{
    const os_init_fn_t *fn_ptr_other_init_start;
    const os_init_fn_t *fn_ptr_other_init_end;
    const os_init_fn_t *fn_ptr;

    fn_ptr_other_init_start = &__os_call_os_board_init_end + 1;
    fn_ptr_other_init_end   = &__os_call_os_init_end - 1;

    for (fn_ptr = fn_ptr_other_init_start; fn_ptr <= fn_ptr_other_init_end; fn_ptr++)
    {
        (void)(*fn_ptr)();
    }
    return;
}

系统执行os_other_auto_init时实现了sh_system_init的自动执行,即使应用层没有显示的去调用它。使用符号段的方式实现初始化函数自动执行,应用层修改软件,增加功能启动或者裁剪,对底层代码无需任何改动。

注意:段中函数类型都是一样的,范例是同一类函数指针,也可以是结构体,需要确保每个成员占用空间大小相同,这样才能逐个遍历。

3、总结

不同编译器对section属性的定义略有差异,但效果相同。

/*Compiler Related Definitions*/
#ifdefined(__CC_ARM)||defined(__CLANG_ARM)  /*ARM Compiler*/
#defineSECTION(x)__attribute__((section(x)))
#elifdefined(__IAR_SYSTEMS_ICC__)/*for IAR Compiler*/
#defineSECTION(x)@x
#elifdefined(__GNUC__)/*GNU GCC Compiler*/
#defineSECTION(x)__attribute__((section(x)))
#elifdefined(__ADSPBLACKFIN__)/*for VisualDSP++Compiler*/
#defineSECTION(x)__attribute__((section(x)))
#elifdefined(_MSC_VER)
#defineSECTION(x)
#elifdefined(__TI_COMPILER_VERSION__)
/*
*The way that TI compiler set section is different from other(at least
*GCC and MDK)compilers.See ARM Optimizing C/C++Compiler 5.9.3 for more
*details.
*/
#defineSECTION(x)
#else
#errornot supported tool chain
#endif

上面的#error也是个应用技巧,配搭#if / #else / #endif在编译阶段即可发现代码问题,一般用于判断宏定义的配置是否在预期之外,编译报错必须修改。

配合C关键字,对代码的安全校验、扩展移植都会有很好的效果。对小型项目、个人独立开发看不出效果,但对复杂的多人合作的项目,合适的关键字对代码的稳定性和架构是锦上添花。





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7573

    浏览量

    133591
  • RT-Thread
    +关注

    关注

    31

    文章

    1234

    浏览量

    39346
  • gcc编译器
    +关注

    关注

    0

    文章

    78

    浏览量

    3294

原文标题:C语言中section关键字的实际作用

文章出处:【微信号:玩点嵌入式,微信公众号:玩点嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言关键字const的几种用法

    本期来讲解一个C语言关键字——const。
    发表于 06-21 11:05 1358次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>关键字</b>const的几种用法

    C语言volatile关键字详解 精选资料分享

    1.volatile和什么有关百度翻译是这样子翻译volatile的:图1-1 百度翻译volatile截图volatile属于C语言关键字,《C Primer Puls》 是这样解
    发表于 07-22 07:20

    C语言中关键字static的作用是什么

    C语言中关键字static的作用是什么?用预处理指令#define 声明一个函数,输入天数得到有多少秒?
    发表于 12-24 06:53

    C语言中的volatile关键字

    volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。
    发表于 05-27 09:32 3240次阅读

    单片机C语言中常用到的关键字及数据类型

    单片机C语言中常用到的关键字及数据类型。
    发表于 11-03 10:57 13次下载

    标准C语言总共有32个关键字

    标准C语言总共有32个关键字
    发表于 01-12 15:59 0次下载

    C语言32个关键字

    C语言32个关键字,感兴趣的小伙伴们可以看看。
    发表于 07-26 16:29 66次下载

    C语言中关键字

    C语言中的入门教程
    发表于 10-14 16:24 3次下载

    浅析C语言中typedef关键字作用

    C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。
    的头像 发表于 11-08 08:42 5845次阅读

    【嵌入式】C语言中volatile关键字

    volatile06. 附录01. volatile概述volatile是C语言中的一个关键字。将变量定义为volatile就表示告诉编译器这个变量可能会被竟想不到地改变,在这种情况下,编译器就不会去假设这个变量的值了,及优化器
    发表于 10-21 10:21 6次下载
    【嵌入式】<b class='flag-5'>C</b><b class='flag-5'>语言中</b>volatile<b class='flag-5'>关键字</b>

    C语言中__attribute__ 关键字的用法

    嵌入式开发,离不开 C 语言C语言中有很多语法会直接或间接影响你代码的质量,下面就来讲讲__attribute__ 关键字的用法。 1.
    发表于 10-19 09:06 1.1w次阅读

    C语言32个关键字可以分为这几类

    C语言是一种面向过程、抽象化的通用程序设计语言,广泛应用于嵌入式底层和系统开发。C语言关键字共有
    的头像 发表于 12-31 15:28 4545次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>32个<b class='flag-5'>关键字</b>可以分为这几类

    浅析C语言中的regiseter关键字

    C语言中重要的关键字有很多,static const extern我们之前都讲过,还有一个面试中出现的频率也比较高:register。
    的头像 发表于 08-25 17:10 984次阅读
    浅析<b class='flag-5'>C</b><b class='flag-5'>语言中</b>的regiseter<b class='flag-5'>关键字</b>

    static关键字的三种用法

    C语言中关键字"static"可以用于不同的上下文,具有不同的作用。以下是"static"
    的头像 发表于 11-10 08:00 400次阅读
    static<b class='flag-5'>关键字</b>的三种用法

    快速掌握C语言关键字

    C语言中的32个关键字你知道多少个呢?根据关键字作用分为四类:数据类型关键字、控制语句
    的头像 发表于 07-06 08:04 182次阅读
    快速掌握<b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>关键字</b>