我有一些嵌入式操作系统功能,我需要在linux机器上进行模拟。我被指示采取的方法是重载嵌入式操作系统功能并将它们包装在POSIX线程中,以便linux机器可以在单元测试期间处理嵌入式操作系统功能等等。
用于创建新线程的嵌入式OS功能是:
OSCreateTask(OStypeTFP functionPointer, OSTypeTcbP taskId, OStypePrio priority)
我需要将OStypeTFP
类型转换为pthread_create
期望的void函数指针:(void * (*)(void *)
是编译器告诉我的预期)
我希望创建一个我可以使用它的typedef:
typedef void (*OStypeTFP)(void);
// Function to run task/thread in
void taskFunction(void) { while(1); }
// Overloaded Embedded OS function
void OSCreateTask(OStypeTFP tFP, OStypeTcbP tcbP, OStypePrio prio)
{
pthread_attr_t threadAttrs;
pthread_t thread;
pthread_attr_init(&threadAttributes);
pthread_create(&thread, &threadAttributes, &tFP, NULL);
}
// Creates a task that runs in taskFunction
OSCreateTask (taskFunction, id, prio);
但是当pthread_create期望functionPointer
void (**)(void)
的类型为void * (*)(void *)
我是否需要以某种方式更改typedef,还是需要进行类型转换?既?
答案 0 :(得分:5)
您需要适配器功能:
typedef void (*OStypeTFP)(void);
// Function to run task/thread in
void taskFunction(void) { while(1); }
void *trampoline(void *arg)
{
OStypeTFP task = (OStypeTFP)arg;
task();
return NULL;
}
// Overloaded Embedded OS function
void OSCreateTask(OStypeTFP tFP, OStypeTcbP tcbP, OStypePrio prio)
{
pthread_attr_t threadAttrs;
pthread_t thread;
pthread_attr_init(&threadAttrs);
pthread_create(&thread, &threadAttrs, trampoline, tFP);
}
// Creates a task that runs in taskFunction
OSCreateTask (taskFunction, id, prio);
当然,只有当系统允许从void *
转换为函数指针时,它才是安全的。但由于我们处于POSIX环境 - 它应该没问题。
答案 1 :(得分:3)
如果我理解正确,嵌入式操作系统上的线程过程的签名是void thread_proc(void)
。另一方面,对于POSIX线程,它是void *thread_proc(void *)
。
您无法使用强制转换和typedef来解决这种差异:您需要安排适当的返回值。你需要一个垫片功能:
typedef void (*OStypeTFP)(void);
struct emu_OSCreateTask_thread_start_data
{
OStypeTFP real_thread_proc;
// possibly other stuff
};
void *emu_OSCreateTask_shim_thread_proc (void *xctx)
{
struct emu_OSCreateTask_thread_start_data *ctx = xctx;
ctx->real_thread_proc();
return 0;
}
void OSCreateTask(OStypeTFP tFP, OStypeTcbP tcbP, OStypePrio prio)
{
pthread_attr_t threadAttrs;
pthread_t thread;
struct emu_OSCreateTask_thread_start_data *ctx =
malloc(sizeof(struct emu_OSCreateTask_thread_start_data));
ctx->real_thread_proc = tFP;
pthread_attr_init(&threadAttributes);
pthread_create(&thread, &threadAttributes,
emu_OSCreateTask_shim_thread_proc, ctx);
}
注意:ctx
在堆上分配并泄露,因为它需要在emu_OSCreateTask_shim_thread_proc
返回之后存活,这可能比OSCreateTask
返回时更晚。如果您不了解有关您尝试模拟的API的更多信息,我无法告诉您应该将它存放在何处,以便在适当时可以释放它,但可能会在某处 。也许在tcbP
?
注2:我使用上下文对象而不是仅填充" real_thread_proc
"在pthread_create
的上下文指针中(如在Sergio的答案中),因为我怀疑你最终需要在垫片中做更多的东西,并且需要更多来自外部环境的数据才能完成它。 (您在POSIX系统上,因此 可以安全地将函数指针填充到void *
中。)