【问题标题】:Does implementation of C libraries depend on OS?C 库的实现是否依赖于操作系统?
【发布时间】:2014-12-18 11:01:01
【问题描述】:

我只是想知道不同的操作系统有不同的功能,但它们的目的是一样的,或者可以说不同的操作系统有不同的系统编程语言(比如 Windows 和 UNIX)。

因此,例如,由于 C 库包含函数的实现,它们的实现必须调用不同的函数(取决于操作系统)来实现相同的东西。这个对吗? 那么,cygwin 中使用的库是否用于编译专门为 Windows 编写的 C 程序,以及 gcc 的库,尤其是为 Linux 编写的库?我对么? 如果不是,那为什么?

【问题讨论】:

  • 这个问题可能不够准确,但我真的不知道如何更好地表达。请原谅我。
  • 您是在询问printf()malloc() 之类的标准函数还是CreateThread() 之类的标准函数?
  • 库包含printf()等函数,它们需要系统调用来实现这些函数。
  • 无论如何,我不明白:您是否在询问诸如 printf 之类的必须提供的功能,但根据环境的不同实现不同?或者询问那些可以但不必表现得与未标准化的函数相同的函数?

标签: c operating-system systems-programming


【解决方案1】:

是的,这是正确的。不同的操作系统有不同的功能做同样的事情。例如,在 Windows 上,您通过调用 CreateThread() 创建线程,而在 linux 上,您调用 pthread_create()

关于 C 运行时,所有操作系统都实现了它们,但有所不同。在 Windows 上,fopen() 是一个将调用 CreateFile() 的包装器,而在 linux 上,fopen() 是一个用于 open() 的包装器。

Cygwin 等添加库以在 Windows 上实现 linux-only 功能。例如,cygwin 将在 Windows 上实现 pthread_create(),通过包装 CreateThread(),就像 MS 为 fopen() 所做的那样。

【讨论】:

  • 谢谢,我希望它应该是这样的,但我对操作系统知之甚少。
  • "而在 linux 上 fopen() 是本机函数" 你错了。你是说 open() 吗?
  • @black 糟糕,我忘了open()
  • pthread_create 更像_beginthreadex,实际上: 调用 C 运行时库 (CRT) 的可执行文件中的线程应该使用 _beginthreadex 和 _endthreadex 函数进行线程管理,而不是比 CreateThread 和 ExitThread;这需要使用 CRT 的多线程版本。如果使用 CreateThread 创建的线程调用 CRT,CRT 可能会在内存不足的情况下终止进程。
  • @MaximYegorushkin 你没抓住重点。 _beginthreadex 也是 CreateThread 的包装器。 pthread_create 在 Windows 中等效为 CreateThread
【解决方案2】:

是的。

添加到ElderBug's answer,作为不同类型系统调用的包装器的 C 库因系统而异。系统调用,例如以下(来自NYU's Operating Systems, Lecture #4),将进程从用户模式转移到主管/内核模式。

注意区分用户模式(包装器)和内核模式(操作系统的实现)的目标,from the lecture:

一个重要的操作系统目标是从用户进程的角度观察简单的过程调用语义。复杂性隐藏在内核本身内部,这是操作系统为用户进程提供更抽象、即更简单的虚拟机的又一个例子。

如您所知,这些示例调用在 Windows 和 Linux 等不同操作系统之间并不相似,但 C 包装函数的名称是 -- 否则,预编译语言本身会因系统而异。

希望有帮助!

【讨论】:

    【解决方案3】:

    是的,你明白了。我能补充的不多。

    但据我所知,操作系统正在为库提供服务,并且它们只是链接在一起。 这样做的原因是,开发系统特定实现的程序员最了解他们自己的系统。 实现fopen() 不仅仅是向硬盘询问其内容的通道。 (你可能知道)

    您必须尊重使用文件描述符的其他实现的许多情况。也许您必须依赖操作系统上特定功能中发生的某些事情,而不需要通用行为。但在您的环境中,这会保持一切正常运行。

    这也是为什么 C 标准说更改标准库的源代码会导致未定义的行为,即使它自己的函数仍然具有相同的行为(试图为您找到引用但无法找到,抱歉。)

    所以它完全是一个优化的东西。可能会有通用实现,但由于大多数情况下整个操作系统都是基于这些实现,每个操作系统都希望让它们在自己的情况下运行得最好。

    (可能不是唯一一个,但我在操作系统开发方面的深度并不像我可以命名的那样深入)

    【讨论】:

      【解决方案4】:

      请记住,库函数有两种类型:实用程序和系统包装器。假设您是一个试图创建可移植库的供应商。

      像 sprintf 和 atoi 这样的实用程序函数在任何实现上都是相同的,因为它们不需要操作系统系统服务。

      通常,您的库中会有一个抽象层。你可能有这样的功能

       void * getBytesFromOS (unsigned int count) ;
      

      分配内存页。对于各种系统,它将具有不同的实现。使用这种接口的 malloc 函数在不同操作系统之间可能 99% 相同。

      【讨论】:

        猜你喜欢
        • 2021-12-31
        • 1970-01-01
        • 2017-01-16
        • 2021-08-11
        • 2017-12-25
        • 2013-09-01
        • 1970-01-01
        • 2021-03-28
        • 1970-01-01
        相关资源
        最近更新 更多