# 开发指导
- [接口说明](#section158501652121514)
- [开发流程](#section5241132917523)
- [编程实例](#section8708112313531)
## 接口说明
**表 1** 功能列表
功能分类
|
接口名
|
描述
|
动态加载功能接口
|
LOS_DynlinkInit
|
初始化动态链接器链表以及互斥锁
|
LOS_SoLoad
|
加载指定路径的共享库
|
LOS_FindSym
|
根据共享库句柄查找指定符号
|
LOS_SoUnload
|
卸载共享库句柄
|
## 开发流程
1. 利用arm-none-eabi-gcc交叉编译器编译共享库并制作FAT或LittleFS文件系统格式镜像烧写至flash中;
2. 在target\_config.h文件中定义宏LOSCFG\_DYNLINK为1使能动态加载模块;
3. 调用LOS\_SoLoad接口加载指定路径下的共享库;
4. 调用LOS\_FindSym接口查找指定符号,获取符号地址;
5. 调用LOS\_SoUnload卸载指定共享库句柄。
> **说明:**
>1. 利用交叉编译器编译共享库所需要的编译选项参考ELF支持规格一节。
>2. 制作文件系统镜像之前需要对特定单板适配FAT或LittleFS文件系统。
>3. 共享库不依赖编译器中的libc库,不支持c++。
>4. 共享库只能依赖内核提供的接口,不能依赖其他共享库。
## 编程实例
实例以cortex-m4单板为例。
1. 共享库示例代码及编译
示例代码主要测试全局符号间的调用功能以及对内核接口maloc、free、memset接口的调用功能。
```
#include
#include
int g_param = 10;
int callee(int a, int b)
{
char *addr = malloc(g_param);
if (addr == NULL) {
return 0;
}
memset(addr, '1', g_param);
free(addr);
return a + b + g_param;
}
int caller(int a, int b)
{
return callee(a, b);
}
```
```
$ arm-none-eabi-gcc -fPIC -shared -mcpu=cortex-m4 -nostdlib -nostartfiles -z max-page-size=4 -o test.so test.c
```
2. 导出共享库中使用到的malloc、free、memset符号,下述代码单独编写成一个.c文件,参与OS编译即可。
```
#include "stdlib.h"
#include "string.h"
SYM_EXPORT(malloc);
SYM_EXPORT(free);
SYM_EXPORT(memset);
```
3. 确定内核的编译环境,在对应编译器的编译链接脚本中添加如下语句,保证符号表信息在编译链接的时候输出到指定的段。
在IAR编译器.icf链接脚本中添加如下语句:
```
keep {section .TABLE.START};
keep {section .sym.*};
keep {section .table.end};
define block SYMBOL_TABLE with fixed order
{
section .TABLE.START,
section .sym.*,
section .table.end
};
place in ROM_region {readonly, block SYMBOL_TABLE};
```
在gcc编译器的.ld链接脚本中添加如下语句:
```
__sym_table_start = .;
KEEP(*( SORT (.sym.*)));
__sym_table_end = .;
```
4. 共享库加载链接、执行与卸载
示例代码主要测试LOS\_SoLoad、LOS\_FindSym、LOS\_SoUnload接口的功能是否正常以及通过LOS\_FindSym查找到的符号的调用是否正常。
```
#include "los_dynlink.h"
VOID DynlinkTest(VOID)
{
VOID *handle = NULL;
INT32 (*func)(INT32, INT32) = NULL;
CHAR *symbolName = "caller";
CHAR *dsoName = "/lib/test.so";
INT32 ret;
handle = (VOID *)LOS_SoLoad(dsoName, NULL);
if (handle == NULL) {
printf("Failed to load so\n");
return;
}
func = (INT32 (*)(INT32, INT32))LOS_FindSym(handle, symbolName);
if (func == NULL) {
printf("Failed to find symbol\n");
LOS_SoUnload(handle);
return;
}
ret = func(1, 1);
if (ret != 12) {
printf("Failed to execute function\n");
LOS_SoUnload(handle);
return;
}
ret = LOS_SoUnload(handle);
if (ret != 0) {
printf("Failed to unload so\n");
}
printf("Success!\n");
}
```
5. 结果验证
```
Success!
```
> **说明:**
>用例中文件系统路径为/lib/test.so;
>可以创建一个任务,在任务中调用DynlinkTest接口进行测试;