共5条
1/1 1 跳转至页
[原创]用函数jump表解决模块加载顺序问题
by amine@263.net
用ld()加载目标模块的顺序很重要。若一个模块在加载时有未解析符号,后面再加载的其他模块对解析这些符号没有帮助。加载模块只能和先他加载的模块连接。例如:有两个模块:app1.o和app2.o,app1.o可以独立运行,而app2.o对app1.o中定义的符号有依赖。这种情况下,ld()会执行必要的连接操作,但是app1.o必须在app2.o之前加载。
但是有时不能保证这种顺序,加载可能导致连接错误“unresolved reference”。这种情况一般可通过主机工具ldarch解决,将这些紧张加载顺序的模块连接在一起。
另外还可以用jump表来解决。这种技巧在高级文件和低级文件之间添加抽象层,低级文件提供函数实现,高级文件通过全局函数指针调用。高级文件加载时不要求调用函数实际存在,只要全局的jump表结构存在就行拉。这样高级文件可先于低级文件加载。但是要求,在使用jump表的模块加载前,需先声明jump表全局指针。
当高级模块需要根据环境调用不同的低级函数实现时,该技巧也有用。单个高级文件可以和多个低级文件配合使用。
使用这种技巧需要3个步骤:在内存中创建空全局jump表;填充jump表中的函数指针;调用jump表函数指针。如下面示例代码:
/*=============================================================================
* jumpTbl.h - Jump table header file
* Declares the jump table structure and necessary functions.
*/
#ifndef __INjumpTblh
#define __INjumpTblh
typedef struct /* Jump table */
{
FUNCPTR addRoutine;
FUNCPTR multRoutine;
FUNCPTR divRoutine;
} JUMP_TBL;
STATUS setupJumpTable(void);
#endif /* __INjumpTblh */
/*=============================================================================
* setupJumpTbl.c – 该文件建立全局访问jump表
* 这是唯一需先加载的文件。应该连接入Vxworks映象。保证后续加载模块可找到jump表
*/
#include "vxWorks.h"
#include "jumpTbl.h"
#include "memLib.h"
#include "stdlib.h"
JUMP_TBL *jumpTable;
/******************************************************************************
* setupJumpTable() - Allocates memory for the jump table.
* 该函数只能运行一次,可以在初始化函数中调用
*/
STATUS setupJumpTable(void)
{
static int alreadySetup = 0; /* Only setup once */
if(alreadySetup == 0) {
if((jumpTable = (JUMP_TBL *)malloc(sizeof(JUMP_TBL)))==NULL)
return(ERROR);
else {
alreadySetup = 1;
return(OK);
}
}
return(OK);
}
/*=============================================================================
* initJumpTbl.c - A low level jump table initialization file.
* 该文件示例jump表初始化,如何使用jump表。
*/
#include "vxWorks.h"
#include "jumpTbl.h"
#include "stdio.h"
IMPORT JUMP_TBL *jumpTable; /* Globally accessable jump table */
/* Forward declarations */
LOCAL int localAdditionRtn(int inputValue1, int inputValue2);
LOCAL int localMultiplyRtn(int inputValue1, int inputValue2);
LOCAL uint_t localDivisionRtn(int inputValue1, int inputValue2);
/*****************************************************************************
* initJumpTable() - Fill the jump table with low level function pointers
*/
void initJumpTable(void)
{
if(jumpTable == NULL) /* Check that table exists already. */
setupJumpTable(); /* If table dosen\''t exist make one. */
/* Fill in the function pointers */
jumpTable->addRoutine = (FUNCPTR)localAdditionRtn;
jumpTable->multRoutine = (FUNCPTR)localMultiplyRtn;
jumpTable->divRoutine = (FUNCPTR)localDivisionRtn;
}
/*****************************************************************************
* localAdditionRtn() - Low level self explanitory static function.
*/
LOCAL int localAdditionRtn(int inputValue1, int inputValue2)
{
return(inputValue1 + inputValue2);
}
/*****************************************************************************
* localMultiplyRtn() - Low level self explanitory static function.
*/
LOCAL int localMultiplyRtn(int inputValue1, int inputValue2)
{
return(inputValue1 * inputValue2);
}
/*****************************************************************************
* localDivisionRtn() - Low level self explanitory static function.
*/
LOCAL uint_t localDivisionRtn(int inputValue1, int inputValue2)
{
if(inputValue2 > 0)
return(inputValue1/inputValue2);
else{
printf("You can\''t divide by ZERO\n");
return(ERROR);
}
}
/*=============================================================================
* callJumpTbl.c - A high level library using jump table function calls
*/
#include "vxWorks.h"
#include "stdio.h"
#include "jumpTbl.h"
IMPORT JUMP_TBL *jumpTable;
void callJumpTable(int inputArg1, int inputArg2)
{
if(jumpTable != NULL) { /* Does jump table exist? */
if(jumpTable->addRoutine != NULL) { /* Anything there? */
printf("Calling jumpTable->addRoutine\n");
printf("The returned value = %d\n",jumpTable->addRoutine(inputArg1,inputArg2));
}
else printf("jumpTable->addRoutine not initialized\n");
if(jumpTable->multRoutine != NULL) { /* Anything there? */
printf("Calling jumpTable->multRoutine\n");
printf("The returned value = %d\n",
jumpTable->multRoutine(inputArg1,inputArg2));
}
else printf("jumpTable->multRoutine not initialized\n");
if(jumpTable->divRoutine != NULL) { /* Anything there? */
printf("Calling jumpTable->divRoutine\n");
printf("The returned value = %d\n",jumpTable->divRoutine(inputArg1,inputArg2));
}
else printf("jumpTable->divRoutine not initialized\n");
}
else printf("jumpTable struct does not exist. Run setupJumpTable()\n");
}
参考“Windriver Tech Tips”的“How to use a jump table”。
[align=right][color=#000066][此贴子已经被作者于2003-4-6 15:58:17编辑过][/color][/align]
关键词: 原创 函数 解决 模块 加载 顺序 问题 文件 t
动态加载是只模块内存重定位是动态的
静态连接是指加载模块的外部符号解析是和编译器linker机制类似
与win的动态库机制,或linux的共享库机制不相同
我对这两种机制不是太熟,不能作具体比较描述:(
主机使用ldarch将app1.o和app2.o合为app.out,
可分离加载, 如果app2.o需要引用app1.o中的符号,app1.o 需先于app2.o加载
也可以单独加载app.out, 不再和两目标模块本身相关
自动保证了两模块之间的符号解析
[align=right][color=#000066][此贴子已经被作者于2003-4-7 9:58:28编辑过][/color][/align]
共5条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 | |
【FRDM-MCXN947评测】核间通信MUTEX被打赏50分 |