Kar*_*uru 17 c compiler-construction operating-system function entry-point
是否可以避免C程序中的入口点(主).在下面的代码中,是否可以在func()不通过main()以下程序调用via的情况下调用该调用?如果是,如何做,何时需要,为什么要给出这样的规定?
int func(void)
{
printf("This is func \n");
return 0;
}
int main(void)
{
printf("This is main \n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
RBe*_*eig 16
当构建嵌入式系统固件直接从ROM运行时,我经常会避免命名入口点,main()以强调代码审查者代码的特殊性.在这些情况下,我提供了C运行时启动模块的自定义版本,因此很容易将其调用替换为main()其他名称,例如BootLoader().
我(或我的供应商)几乎总是必须在这些系统中自定义C运行时启动,因为RAM要求初始化代码才能开始正常运行并不罕见.例如,典型的DRAM芯片需要其控制硬件的惊人数量的配置,并且在它们有用之前通常需要大量(数千个总线时钟周期)延迟.在完成之前,甚至可能没有放置调用堆栈的位置,因此启动代码可能无法调用任何函数.即使RAM器件在上电时工作,也几乎总是有一些芯片选择硬件或一两个FPGA需要初始化才能让C运行时开始初始化.
当用C编写的程序加载并启动时,某些组件负责使main()存在的环境存在.在Unix,Linux,Windows和其他交互式环境中,大部分工作是加载程序的OS组件的自然结果.但是,即使在这些环境中,也需要进行一些初始化工作才能main()调用.如果代码实际上是C++,那么可能会有大量工作,包括为所有全局对象实例调用构造函数.
所有这些的细节由链接器及其配置和控制文件处理.链接器ld(1)有一个非常复杂的控制文件,它准确地告诉它在输出中包含哪些段,在什么地址以及以什么顺序包含.查找链接器控制文件,您隐式使用的工具链和读取它可能是有益的,链接器本身的参考手册和您的可执行文件必须遵循的ABI标准才能运行.
编辑:更直接地回答在更常见的背景下提出的问题:"你能打电话给foo而不是主?" 答案是"可能,但只是因为很棘手".
在Windows上,可执行文件和DLL的文件格式几乎相同.可以编写一个程序来加载在运行时命名的任意DLL,并在其中查找任意函数并调用它.一个这样的程序实际上作为标准Windows发行版的一部分提供:rundll32.exe.
由于.EXE文件可以由处理.DLL文件的相同API加载和检查,原则上如果.EXE具有命名该函数的EXPORTS部分foo,则可以编写类似的实用程序来加载和调用它.main当然,你不需要做任何特别的事情,因为这将是自然的切入点.当然,在实用程序中初始化的C运行时可能与可执行文件链接的C运行时不同.(Google为"DLL Hell"提示.)在这种情况下,您的实用程序可能需要更智能.例如,它可以充当调试器,以断点加载EXE main,运行到该断点,然后将PC更改为指向或进入foo并从那里继续.
因为.so文件在某些方面与真正的可执行文件类似,所以在Linux上可能存在某种类似的技巧.当然,可以使用像调试器一样的方法.