C 试图理解函数指针的用法

C 试图理解函数指针的用法,c,linux,u-boot,C,Linux,U Boot,这是从中启动内核的函数: /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) { #ifdef CONFIG_ARM64 void (*kernel_entry)(void *fdt_addr); int fake = (flag & BOOTM_STATE_OS_FAKE_GO); kernel_entry = (void (*)(void *fdt_addr))ima

这是从中启动内核的函数:

/* Subcommand: GO */
static void boot_jump_linux(bootm_headers_t *images, int flag)
{
#ifdef CONFIG_ARM64
void (*kernel_entry)(void *fdt_addr);
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);

kernel_entry = (void (*)(void *fdt_addr))images->ep;

debug("## Transferring control to Linux (at address %lx)...\n",
(ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);

announce_and_cleanup(fake);

if (!fake)
kernel_entry(images->ft_addr);
#else
unsigned long machid = gd->bd->bi_arch_number;
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);

kernel_entry = (void (*)(int, int, uint))images->ep;

s = getenv("machid");
if (s) {
strict_strtoul(s, 16, &machid);
printf("Using machid 0x%lx from environment\n", machid);
}

debug("## Transferring control to Linux (at address %08lx)" \
"...\n", (ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake);

if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
r2 = (unsigned long)images->ft_addr;
else
r2 = gd->bd->bi_boot_params;

if (!fake)
kernel_entry(0, machid, r2);
#endif
}
我很难理解
kernel\u entry
是如何在这里工作的。特别是在最后一行中,它被用作:

   kernel_entry(0, machid, r2);
那么
kernel\u entry()
的定义在哪里呢?我未能在整个u-boot和内核源代码中找到

更新

我在这里重新表述我的问题:

假设
kernel\u entry
是指向函数的指针,定义如下:

bootm_headers_t *images
kernel_entry = (void (*)(int, int, uint))images->ep;
然后在程序的某个地方,它被称为:

 kernel_entry(0, machid, r2);

我知道作为一个指针,
kernel\u条目
应该存储函数的地址。但我想了解对这三个参数将执行哪些操作。为什么会有这些参数?

内核项变量及其类型的声明,它是一个指向函数的指针,该函数取
int
int
uint
并返回
void
(可能是最容易混淆的部分),如下所示:

void (*kernel_entry)(int zero, int arch, uint params);
赋值,
images->ep
被转换到所需的签名函数指针中,并放入变量中:

kernel_entry = (void (*)(int, int, uint))images->ep;
最后,调用该函数:

kernel_entry(0, machid, r2);
请注意,如果定义了CONFIG_ARM64,则函数
内核\u条目
指向具有不同签名:

void (*kernel_entry)(void *fdt_addr); //takes one void* param and returns void

U-Boot在其可寻址内存空间中具有内核映像,读取该映像中包含的地址(在images->ep处),并分支到该入口点地址

“kernel_entry()的定义”实际上在内核源代码中,arch/arm/boot/compressed/head.S处的标签“start”就是您要查找的


为了理解内核引导过程,我的权威教程是Hallinan“嵌入式Linux入门”的第5章函数将对这三个参数(即int、int、uint)执行什么操作?它不是一个函数,而是一个指针强制转换,因此您可以使用三个参数调用kernel\u entry,前两个参数为
int
,第三个参数为
uint
。你能解释一下“kernel\u entry=(void(*)(int,int,uint))images->ep;”中到底发生了什么吗然后作为答案回答?您介意格式化代码以使其可读吗?kernel_条目是指向“函数”的指针。功能在哪里?它必须有一个显示如何处理这三个参数的定义…该函数是通过
images->ep
提供的。它是在调用
boot\u jump\u linux
之前在其他地方定义的。我也找不到关于ep的任何信息。它应该是一个结构?功能定义是不相关的。正如您可以将
*int
强制转换为
*float
,您也可以将函数指针强制转换为其他任何内容。很明显,这段代码的作者将类型检查抛出了窗口。这就是指针的要点:不再使用名称。在这里,我给你举了个例子:谢谢你的信息。但实际上,任何地方都没有这样的文件。你能核对一下文件名/位置吗?我还发现了另一个.S文件:arch/arm/kernel/head common.S,它有thsi标签。哦,非常抱歉,我的打字错误,它是arch/arm/boot/compressed/head.S。这个“开始”标签对于我的Cortex-A9目标上的v3.14.3绝对正确。