C 语言的运行时系统

Seb*_*Nag 3 c computer-science

根据维基百科,执行模型

语言规范的一部分,并作为语言实现的一部分来实现。

它进一步定义了

执行顺序可以静态选择[...],但一小部分必须在执行过程中动态选择。

[...] 静态选择通常在编译器内部实现,在这种情况下,工作顺序由指令放入可执行二进制文件的顺序表示。然后,动态选择将在语言的运行时系统内实现。
运行时系统可以是一个库,由编译器插入的指令调用,或者运行时系统可以直接嵌入到可执行文件中,例如通过插入分支指令,这对下一步要执行的工作进行动态选择。

维基百科将运行时系统指定为

任何不直接由程序工作的行为都是运行时系统行为。该定义包括运行时系统的一部分,例如在函数调用之前将参数放入堆栈、磁盘 I/O 的行为以及与并行执行相关的行为。

另外

也是正在运行的程序与运行时环境交互的网关,它不仅包含程序执行期间可访问的状态值,还包含程序执行期间可通过键盘交互的活动实体,例如磁盘驱动器和人。

它进一步指出,

运行时系统实现的更高级别的行为可能包括诸如在屏幕上绘制文本或建立互联网连接之类的任务。
通常情况下,操作系统也提供这些类型的行为[...]运行时系统被实现为抽象层,它将运行时系统的调用转换为操作系统的调用。这隐藏了不同操作系统提供的服务的复杂性或变化。[对于我来说,关于 Linux 内核,这基本上是系统调用]
这也意味着操作系统内核本身可以被视为运行时系统,并且调用操作系统行为的操作系统调用集可以被视为与运行时系统的交互。

我知道必须有某种运行时环境,例如 Linux 内核,将编译后的可执行文件加载到内存中,启动进程,允许子线程之类的东西。内核本身是用语言编写的C,不能被视为C语言的“运行时系统”。然而,它提供了诸如malloc()和 之类的功能free(),这些功能是运行时系统的重要组成部分。

Q那么到底什么是运行时系统呢C?有没有一个不模糊的定义?它是独立内核+编译器的混合物吗?

Die*_*Epp 5

“运行时”和“标准库”之间的界限很模糊,并且没有真正达成一致。“内核”通常是特权代码和非特权代码之间的一条硬线。不同部件的标记方式也会因平台而异,因此实际上不可能给出通用答案。

但是,您可以针对特定系统稍微回答这个问题。例如,以下是它在具有 GNU 工具链的典型 Linux 系统上的工作方式:

  • 程序代码编译为一堆*.o文件并链接到可执行文件。

  • “C 运行时库”。这可以作为一些额外*.o文件(crt1.ocrti.ocrtn.o)使用,编译器会隐式链接到您的程序中。这个库相当小,而且只做两件事。它提供_start,加载argcargv,调用main,并exitmain返回时调用(某种程度上)。该库还调用全局构造函数和析构函数——这在 C 中通常不存在,但您可以使用语言扩展来创建它们。

  • “C 标准库”。它可以作为怪物*.so*.a库使用,编译器隐式链接到您的程序中。它实现了纯函数,如strcpyatoi,以及更复杂的系统,如mallocfree,并且还提供了一组系统调用,它们可以是 Linux 系统调用的瘦包装器,如open,更复杂的包装器,更通用的系统调用,如forkclone,或者可以是 VDSO 加速的喜欢gettimeofdayclock_gettime

这并不是“什么是 C 运行时”的明确答案,因为“运行时”实际上并没有严格的定义。然而,Linux 上有一个称为 C 运行时库”的库,其他系统上也存在类似的库。搜索往往可以直接阅读源代码,也可以反汇编(不是很长)。

在某些平台上,这一切都会发生变化,例如嵌入式平台,您可能只有一个大的“标准库”,其中包含您需要的一切,但没有内核。

  • @Olaf:如果您认为问题太广泛并且不应该得到回答,那么适当的行动方针是对问题发表评论、标记问题、投票结束问题或否决问题。正如我所看到的,这些事情中精确地为零,我不确定我是否理解你为什么在这里和我谈论这个问题。我也不认为我们需要对所有事情给出百科全书式的答案——你当然可以自由地不同意,但你没有对我的答案发表任何评论,只是对问题本身发表评论。 (2认同)