44

好吧,标题说明了一切。main()函数对于 C 程序来说是绝对必要的吗?

我问这个是因为我正在查看 Linux 内核代码,但我没有看到 main() 函数。

4

7 回答 7

64

不,ISO C 标准规定main只有托管环境(例如具有底层操作系统的环境)才需要一个功能。

对于像嵌入式系统(或操作系统本身)这样的独立环境,它是由实现定义的。从 C99 开始5.1.2

定义了两种执行环境:独立和托管。在这两种情况下,程序启动都是在执行环境调用指定的 C 函数时发生的。

在独立环境中(C 程序的执行可能在没有操作系统的任何好处的情况下发生),程序启动时调用的函数的名称和类型是实现定义的。

至于 Linux 本身是如何启动的,Linux 内核的起点是start_kernel,但要更完整地了解整个启动过程,您应该从这里开始。

于 2010-11-06T15:32:39.810 回答
10

嗯,不,但是...

C99 指定main()在托管环境中“在程序启动时”调用它,但是,您不必使用 C 运行时支持。您的操作系统执行图像文件并在链接器提供的地址处启动程序。

如果您愿意编写程序以符合操作系统的要求而不是 C99 的要求,则可以不使用 main()。但是,系统越现代(和复杂),您在 C 库假设使用标准运行时启动时遇到的麻烦就越大。

这是Linux的示例...

$ cat > nomain.S
.text
_start:
    call    iamnotmain
    movl    $0xfc, %eax
    xorl    %ebx, %ebx
    int     $0x80
.globl _start
$ cat > demo.c

void iamnotmain(void) {
    static char s[] = "hello, world\n";
    write(1, s, sizeof s);
}
$ as -o nomain.o nomain.S
$ cc -c demo.c
$ ld -static nomain.o demo.o -lc
$ ./a.out
hello, world

不过,它现在可以说不是“C99 程序”,只是一个带有用 C 语言编写的目标模块的“Linux 程序”。

于 2010-11-08T00:25:05.573 回答
9

main()函数由 libc 中包含的目标文件调用。由于内核不链接到 libc,它有自己的入口点,用汇编程序编写。

于 2010-11-06T15:32:52.393 回答
3

Paxdiablo 的回答涵盖了两种你不会遇到主的情况。让我再补充几个:

  • 许多其他程序(例如浏览器或文本编辑器等)的插件系统没有main().
  • 用 C 编写的 Windows 程序没有main(). (他们有一个WinMain()代替。)
于 2010-11-06T15:40:10.417 回答
0

操作系统加载程序必须调用单个入口点;在 GNU 编译器中,入口点定义在 crt0.o 链接目标文件中,其来源是汇编文件 crt0.s - 在执行各种运行时启动任务(例如建立堆栈,静态初始化)。因此,在构建链接默认 crt0.o 的可执行文件时,您必须有一个 main(),否则会出现链接器错误,因为在 crt0.o 中 main() 是一个未解析的符号。

修改 crt0.s 以调用不同的入口点是可能的(如果有些不正当和不必要的话)。只需确保为您的项目创建这样一个目标文件,而不是修改默认版本,否则您将破坏该机器上的每个构建。

操作系统本身有自己的 C 运行时启动(将从引导加载程序调用),因此可以调用它希望的任何入口点。我没有查看 Linux 源代码,但想象一下它有自己的 crt0.s,可以调用 C 代码入口点的任何内容。

于 2010-11-06T22:32:50.737 回答
0

main 由 glibc 调用,它是应用程序的一部分(环 3),而不是内核(环 0)。
驱动程序有另一个入口点,例如基于 WDM 的 Windows 驱动程序是从 DRIVERENTRY 开始的

于 2010-11-07T14:16:38.950 回答
-2

在机器语言中,事情是按顺序执行的,先执行的先执行。因此,编译器默认调用您的 main 方法以符合 C 标准。

你的程序像一个库一样工作,它是一个编译函数的集合。库和标准可执行文件之间的主要区别在于,对于第二个,编译器生成汇编代码,该代码调用程序中的函数之一。

但是您可以编写汇编代码来调用您的任意 C 程序函数(实际上与调用库函数的工作方式相同),这与其他可执行文件的工作方式相同。但问题是你不能在普通的标准 C 中做到这一点,你必须求助于汇编甚至其他一些编译器特定的技巧。

这旨在作为一般和肤浅的解释,我故意避免了一些技术差异,因为它们似乎不相关。

于 2010-11-06T18:27:29.903 回答