根据维基百科,execution model是
语言规范的一部分,并作为语言实现的一部分实现。
它进一步定义了
执行顺序可以静态选择[...]但必须动态选择一小部分,因为执行过程。
[...]静态选择通常在编译器中实现,在这种情况下,工作顺序由指令放入可执行二进制文件的顺序表示。然后,动态选择将在语言的运行时系统中实现 运行时系统可以是库,由编译器插入的指令调用,或者运行时系统可以直接嵌入到可执行文件中,例如通过插入分支指令,分支指令动态选择下一步要执行的工作。
维基百科将runtime system指定为
任何不直接影响程序工作的行为都是运行时系统行为。该定义包括作为运行时系统的一部分,例如在函数调用之前将参数放入堆栈,磁盘I / O的行为以及与并行执行相关的行为。
另外
也是运行程序与运行时环境交互的网关,运行环境不仅包含程序执行期间可访问的状态值,还包含可在程序执行期间与磁盘驱动器和人员交互的活动实体,通过键盘。
它进一步指出,
运行时系统实现的高级行为可能包括诸如在屏幕上绘制文本或建立Internet连接等任务 通常情况下,操作系统也提供这些行为[...]运行时系统实现为抽象层,将运行时系统的调用转换为操作系统的调用。这隐藏了不同操作系统提供的服务的复杂性或变化。 [基本上是系统调用我,关于Linux内核]
这也意味着OS内核本身可以被视为运行时系统,并且调用OS行为的OS调用集可以被视为与运行时系统的交互。
我知道必须有某种运行时环境,比如Linux内核,将已编译的可执行文件加载到内存中,启动进程,允许子线程和类似的东西。内核本身是用C
编写的,不能被视为C
语言的“运行时系统”。但是,它提供了malloc()
和free()
等函数,它们是运行时系统的基本组成部分。
问那么C
的运行时系统究竟是什么?它的定义是否有任何模糊的定义?它是一个独立内核+编译器的混合体吗?
答案 0 :(得分:0)
不,内核不提供像malloc()
和free()
这样的函数,尽管这些函数最终依赖于内核提供的内存。
C的运行时系统是C运行时库,由编译器的供应商提供。当您#include <stdio.h>
或类似的任何内容时,您指定要使用这些库中的功能。如果仔细查看make过程的链接步骤,您将看到编译器生成的目标文件与C运行时库(也简称为“C runtime”)一起被喜欢,以生成可执行文件
然后,稍后,操作系统将加载并执行您的程序,但操作系统不知道,也不关心您的程序编写的语言,以及它正在使用哪种运行时支持。
答案 1 :(得分:0)
“运行时”和“标准库”之间的界限很模糊,并没有真正达成一致。在特权代码和非特权代码之间,“内核”通常是一条更难的线。不同部分的标记方式也因平台而异,因此无法给出一般性答案。
但是,您可以针对特定系统稍微回答一下这个问题。例如,以下是它在具有GNU工具链的典型Linux系统上的工作方式:
程序代码,编译为一堆*.o
个文件并链接到可执行文件中。
“C运行时库”。这可以作为一些额外的*.o
文件(crt1.o
,crti.o
,crtn.o
)使用,编译器会隐式链接到您的程序中。这个库相当小,只做了两件事。它提供_start
,加载argc
和argv
,调用main
,并在exit
返回时调用main
(排序)。该库还调用全局构造函数和析构函数 - 它们通常不存在于C中,但您可以使用语言扩展来创建它们。
“C标准库”。这可以作为怪物*.so
或*.a
库使用,编译器会隐式链接到您的程序中。它实现了strcpy
和atoi
之类的纯函数,以及malloc
和free
等更复杂的系统,还提供了一组系统调用,可以是薄包装器像open
这样的Linux系统调用,包括fork
和clone
等更通用系统调用的更复杂包装,或者像gettimeofday
和clock_gettime
一样可以加速VDSO。
这不是“什么是C运行时”的明确答案,因为开始时并没有真正严格定义“运行时”。但是,在Linux上有一个称为“C运行时库”的库,其他系统上也存在类似的库。如果你搜索它,你通常可以直接阅读源代码,或者你可以反汇编它(它不是很长)。
这将在某些平台上发生变化,例如嵌入式平台,你可能只有一个大的“标准库”,它拥有你需要的一切,而且没有内核。