1# 开发指导<a name="ZH-CN_TOPIC_0000001182409801"></a> 2 3- [接口说明](#section158501652121514) 4- [开发流程](#section5241132917523) 5- [编程实例](#section8708112313531) 6 7## 接口说明<a name="section158501652121514"></a> 8 9**表 1** 功能列表 10 11<a name="table18293928155615"></a> 12<table><thead align="left"><tr id="row129362875613"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p19444103765618"><a name="p19444103765618"></a><a name="p19444103765618"></a>功能分类</p> 13</th> 14<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p944473716569"><a name="p944473716569"></a><a name="p944473716569"></a>接口名</p> 15</th> 16<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p144445378565"><a name="p144445378565"></a><a name="p144445378565"></a>描述</p> 17</th> 18</tr> 19</thead> 20<tbody><tr id="row16964173231"><td class="cellrowborder" rowspan="4" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p106040172412"><a name="p106040172412"></a><a name="p106040172412"></a>动态加载功能接口</p> 21</td> 22<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p136961178237"><a name="p136961178237"></a><a name="p136961178237"></a>LOS_DynlinkInit</p> 23</td> 24<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p3697131710237"><a name="p3697131710237"></a><a name="p3697131710237"></a>初始化动态链接器链表以及互斥锁</p> 25</td> 26</tr> 27<tr id="row18697201714231"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p66971817102319"><a name="p66971817102319"></a><a name="p66971817102319"></a>LOS_SoLoad</p> 28</td> 29<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1569711715233"><a name="p1569711715233"></a><a name="p1569711715233"></a>加载指定路径的共享库</p> 30</td> 31</tr> 32<tr id="row18697117132313"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1697161732312"><a name="p1697161732312"></a><a name="p1697161732312"></a>LOS_FindSym</p> 33</td> 34<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p5697917132313"><a name="p5697917132313"></a><a name="p5697917132313"></a>根据共享库句柄查找指定符号</p> 35</td> 36</tr> 37<tr id="row1925202662319"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p7925526112315"><a name="p7925526112315"></a><a name="p7925526112315"></a>LOS_SoUnload</p> 38</td> 39<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p492520269233"><a name="p492520269233"></a><a name="p492520269233"></a>卸载共享库句柄</p> 40</td> 41</tr> 42</tbody> 43</table> 44 45## 开发流程<a name="section5241132917523"></a> 46 471. 利用arm-none-eabi-gcc交叉编译器编译共享库并制作FAT或LittleFS文件系统格式镜像烧写至flash中; 482. 在target\_config.h文件中定义宏LOSCFG\_DYNLINK为1使能动态加载模块; 493. 调用LOS\_SoLoad接口加载指定路径下的共享库; 504. 调用LOS\_FindSym接口查找指定符号,获取符号地址; 515. 调用LOS\_SoUnload卸载指定共享库句柄。 52 53> **说明:** 54>1. 利用交叉编译器编译共享库所需要的编译选项参考ELF支持规格一节。 55>2. 制作文件系统镜像之前需要对特定单板适配FAT或LittleFS文件系统。 56>3. 共享库不依赖编译器中的libc库,不支持c++。 57>4. 共享库只能依赖内核提供的接口,不能依赖其他共享库。 58 59## 编程实例<a name="section8708112313531"></a> 60 61实例以cortex-m4单板为例。 62 631. 共享库示例代码及编译 64 65 示例代码主要测试全局符号间的调用功能以及对内核接口maloc、free、memset接口的调用功能。 66 67 ``` 68 #include <stdlib.h> 69 #include <string.h> 70 71 int g_param = 10; 72 73 int callee(int a, int b) 74 { 75 char *addr = malloc(g_param); 76 if (addr == NULL) { 77 return 0; 78 } 79 80 memset(addr, '1', g_param); 81 82 free(addr); 83 return a + b + g_param; 84 } 85 86 int caller(int a, int b) 87 { 88 return callee(a, b); 89 } 90 ``` 91 92 ``` 93 $ arm-none-eabi-gcc -fPIC -shared -mcpu=cortex-m4 -nostdlib -nostartfiles -z max-page-size=4 -o test.so test.c 94 ``` 95 962. 导出共享库中使用到的malloc、free、memset符号,下述代码单独编写成一个.c文件,参与OS编译即可。 97 98 ``` 99 #include "stdlib.h" 100 #include "string.h" 101 102 SYM_EXPORT(malloc); 103 SYM_EXPORT(free); 104 SYM_EXPORT(memset); 105 ``` 106 1073. 确定内核的编译环境,在对应编译器的编译链接脚本中添加如下语句,保证符号表信息在编译链接的时候输出到指定的段。 108 109 在IAR编译器.icf链接脚本中添加如下语句: 110 111 ``` 112 keep {section .TABLE.START}; 113 keep {section .sym.*}; 114 keep {section .table.end}; 115 define block SYMBOL_TABLE with fixed order 116 { 117 section .TABLE.START, 118 section .sym.*, 119 section .table.end 120 }; 121 place in ROM_region {readonly, block SYMBOL_TABLE}; 122 ``` 123 124 在gcc编译器的.ld链接脚本中添加如下语句: 125 126 ``` 127 __sym_table_start = .; 128 KEEP(*( SORT (.sym.*))); 129 __sym_table_end = .; 130 ``` 131 1324. 共享库加载链接、执行与卸载 133 134 示例代码主要测试LOS\_SoLoad、LOS\_FindSym、LOS\_SoUnload接口的功能是否正常以及通过LOS\_FindSym查找到的符号的调用是否正常。 135 136 ``` 137 #include "los_dynlink.h" 138 139 VOID DynlinkTest(VOID) 140 { 141 VOID *handle = NULL; 142 INT32 (*func)(INT32, INT32) = NULL; 143 CHAR *symbolName = "caller"; 144 CHAR *dsoName = "/lib/test.so"; 145 INT32 ret; 146 147 handle = (VOID *)LOS_SoLoad(dsoName, NULL); 148 if (handle == NULL) { 149 printf("Failed to load so\n"); 150 return; 151 } 152 153 func = (INT32 (*)(INT32, INT32))LOS_FindSym(handle, symbolName); 154 if (func == NULL) { 155 printf("Failed to find symbol\n"); 156 LOS_SoUnload(handle); 157 return; 158 } 159 160 ret = func(1, 1); 161 if (ret != 12) { 162 printf("Failed to execute function\n"); 163 LOS_SoUnload(handle); 164 return; 165 } 166 167 ret = LOS_SoUnload(handle); 168 if (ret != 0) { 169 printf("Failed to unload so\n"); 170 } 171 172 173 printf("Success!\n"); 174 } 175 ``` 176 1775. 结果验证 178 179 ``` 180 Success! 181 ``` 182 183 184> **说明:** 185>用例中文件系统路径为/lib/test.so; 186>可以创建一个任务,在任务中调用DynlinkTest接口进行测试; 187 188