我知道这里有很多关于采用可变数量参数的函数的问题。我还知道有很多关于 stdarg.h 及其宏的文档。我还知道类似 printf 的函数如何接受可变数量的参数。我已经尝试过所有这些替代方案,但它们对我没有帮助。因此,在将此问题标记为重复之前,请记住这一点。
我正在研究一个小型嵌入式操作系统的进程管理功能,并且一直致力于设计一个函数,该函数可以创建运行具有可变数量参数的函数的进程。以下是我希望 API 的简化版本:
// create a new process
// * function is a pointer to the routine the process will run
// * nargs is the number of arguments the routine takes
void create(void* function, uint8_t nargs, ...);
void f1();
void f2(int i);
void f3(float f, int i, const char* str);
int main()
{
create(f1, 0);
create(f2, 1, 9);
create(f3, 3, 3.14f, 9, "string");
return 0;
}
这是系统调用create
实现相关部分的伪代码:
void create(void* function, uint8_t nargs, ...)
{
process_stack = create_stack();
first_arg = &nargs + 1;
copy_args_list_to_process_stack(process_stack, first_arg);
}
当然,我需要知道调用约定,以便能够从 create
的激活记录复制到新的进程堆栈,但这不是问题。问题是我需要复制多少字节。尽管我知道需要复制多少个参数,但我不知道每个参数占用多少空间。所以我不知道什么时候停止复制。
Xinu Operating System做了与我想做的非常相似的事情,但我努力理解代码但没有成功。我将在这里记录 Xinu 的 create
函数的一个非常简化的版本。也许有人理解并帮助我。
pid32 create(void* procaddr, uint32 ssize, pri16 priority, char *name, int32 nargs, ...)
{
int32 i;
uint32 *a; /* points to list of args */
uint32 *saddr; /* stack address */
saddr = (uint32 *)getstk(ssize); // return a pointer to the new process's stack
*saddr = STACKMAGIC; // STACKMAGIC is just a marker to detect stack overflow
// this is the cryptic part
/* push arguments */
a = (uint32 *)(&nargs + 1); /* start of args */
a += nargs -1; /* last argument */
for ( ; nargs > 4 ; nargs--) /* machine dependent; copy args */
*--saddr = *a--; /* onto created process's stack */
*--saddr = (long)procaddr;
for(i = 11; i >= 4; i--)
*--saddr = 0;
for(i = 4; i > 0; i--) {
if(i <= nargs)
*--saddr = *a--;
else
*--saddr = 0;
}
}
我被困在这一行:a += nargs -1;
。这应该将指针 a
4*(nargs
- 1) 在内存中向前移动,对吧?如果参数的大小不是 4 个字节怎么办?但这只是第一个问题。我也不明白接下来的代码行。
最佳答案
如果您正在编写操作系统,您还定义了调用约定,对吗?根据需要确定 sizeof(void*) 和 pad 的参数大小。
关于c - 如何创建一个运行具有可变数量参数的例程的进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49290078/