【问题标题】:Runtime System in CC中的运行时系统
【发布时间】:2017-03-10 21:45:45
【问题描述】:

根据维基百科,execution model

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

它进一步定义了

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

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

维基百科将runtime system指定为

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

另外

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

它进一步指出,

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

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

Q 那么C的运行时系统到底是什么?是否有任何不模糊的定义?它是自立内核 + 编译器的混合体吗?

【问题讨论】:

  • The kernel itself is written in C and can not be viewed as the "runtime system" of the C language。为什么不? C 有独立和托管的实现。内核是独立的,即它提供了运行所需的一切。普通的 C 应用程序是托管的,并且依赖于 libc,它本身取决于内核,才能正常运行。
  • runtime system of C 怎么可能是 VAX 系统上的 mixture of Linux Kernel + Compiler?或 MS-Windows,或 BSD,或......?
  • @a3f 以及它在使用 C 的嵌入式系统上的裸机编程表现如何? µC 的供应商是否提供了实现内核基本功能的运行时库,以便正确编译和运行 C 程序?
  • "it (kernel) 提供类似 malloc() 和 free() 的函数" --> 标准库提供malloc() 等,而不是内核。库是否使用内核不是 C 的一部分。
  • @KevinDTimm 为什么要抓取过去的例子?只看裸机系统。

标签: c computer-science


【解决方案1】:

“运行时”和“标准库”之间的界线很模糊,也没有真正达成一致。 “内核”通常是特权代码和非特权代码之间的一条更严格的界限。不同部分的标注方式也会因平台而异,因此无法给出一个笼统的答案。

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

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

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

  • “C 标准库”。这是一个怪物*.so*.a 库,编译器会隐式链接到您的程序中。它实现了像strcpyatoi这样的纯函数,以及像mallocfree这样更复杂的系统,并且还提供了一组系统调用,可以是像open这样的Linux系统调用的瘦包装器,更多围绕更通用的系统调用(如 forkclone)的复杂包装器,或者可以像 gettimeofdayclock_gettime 那样进行 VDSO 加速。

这不是对“什么是 C 运行时”的明确回答,因为对于“运行时”并没有真正严格的定义。但是,在 Linux 上有一个库被称为“C 运行时库”,其他系统上也存在类似的库。经常搜索可以直接看源码,也可以反汇编(不是很长)。

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

【讨论】:

  • 这个问题太宽泛了。它不仅明确地针对 Linux 系统(或具有一般操作系统的系统)。
  • @Olaf:同意这个问题很广泛——Linux 只是作为它在一个特定平台上如何工作的说明性示例。
  • @Olaf:您认为答案是否包含错误,或者我只是不够清楚,Linux 示例仅是说明性的?
  • 正如我所写,这个问题太宽泛了。一个可接受的答案需要一些详细信息。有太多不同的 C 实现/运行时环境。该标准有意不指定这一点,例如爪哇。如果我目前没有缺票,我会立即提交问题。
  • @Olaf:如果您认为问题过于宽泛,不应该回答,那么适当的做法是对问题发表评论,标记问题,投票结束问题,或对问题投反对票。正如我所看到的,这些事情中的零已经完成了,我不确定我是否理解你为什么在这里和我谈论这个问题。我也不认为我们需要对所有事情都给出百科全书式的答案——你当然可以不同意,但你没有对我的答案做出任何评论,只是关于问题本身。
【解决方案2】:

不,内核不提供像malloc()free() 这样的函数,尽管这些函数最终都依赖于内核提供的内存。

C 的运行时系统是 C 运行时库,由您的编译器供应商提供。当您#include <stdio.h> 或类似的东西时,您正在指定要使用这些库中的功能。如果您仔细查看 make 过程的链接步骤,您会发现编译器生成的目标文件与 C 运行时库(也简称为“C 运行时”)一起用于生成可执行文件.

然后,稍后,操作系统将加载并执行您的程序,但操作系统不知道也不关心您的程序是用哪种语言编写的,以及它使用了哪种运行时支持。

【讨论】:

  • C 运行时库是特定于底层操作系统的吗?
  • @SebNag 是的,每个 C 运行时库实现都依赖于操作系统。它本质上是标准C库规定的接口与底层操作系统提供的接口之间的翻译层。正是为了让您可以以可移植的方式针对标准 C 库接口进行编码,而不必太担心您在哪个操作系统上运行。
  • C 中不需要库。
猜你喜欢
  • 2019-11-24
  • 1970-01-01
  • 2012-02-14
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多