【问题标题】:Computer Architecture: How do applications communicate with an operating system? [closed]计算机体系结构:应用程序如何与操作系统通信? [关闭]
【发布时间】:2016-04-13 22:08:35
【问题描述】:

前奏:诚然,这是一个关于计算机体系结构的相当广泛的问题,但我从其他人那里听到并且我自己也经常想知道的问题。我也不认为对此有直接或快速的答案。不过,我希望精通系统架构的人能提供一些见解。

一些背景知识:我主要是一名全栈开发人员,主要关注 Web 技术和数据库。我确实有一些 C 方面的背景,并且修补过很多低级的东西,但那是很久以前的事了,而且是非学术的。因此,我从来没有深入了解过操作系统架构,而这是我无法理解的部分。我知道完成这些任务的各种技术和方法(尤其是在更高级别上使用为此目的的技术),但是我缺乏对低级物流如何发生的整体图片/理解 - 特别是在操作系统级别.

一般的问题是:在“容器”内运行的应用程序实际上如何与该容器的运行实例通信? “容器”是指已经加载到内存中的运行代码实例(此类代码的示例可以是操作系统、图形绘制接口、应用服务器、驱动程序等)。

此外,此问题仅适用于编译后的代码,以及在同一台机器上运行的系统之间的通信。

例如

假设我构建了一个简单的库,其目的是在屏幕上绘制一个像素。假设这个库有一个方法,drawPixel(int x, int y)

库本身管理自己的绘图上下文(可以是从原始 SVGA 缓冲区到桌面窗口的任何内容)。使用此 API 的应用程序只需动态链接到库,并调用 drawPixel 方法,而无需知道调用后库的确切操作。

在底层,这个drawPixel 方法应该绘制到桌面上的一个窗口,如果它在第一次调用时不存在,则创建它。

但是,从技术上讲,如果设置如此简单明了,每个调用应用程序将“拉并运行”drawPixel 及其依赖项中的所有代码,从而有效地导致每个正在运行的应用程序拥有自己的整个调用链的运行实例(因此,如果它被 5 个不同的应用程序调用,您最终会得到 5 个不同的窗口,而不是一个窗口的共享上下文)。 (我希望我解释得对)

那么,我的问题是,这种“共享”在现代操作系统中是如何发生的?

drawPixel 的代码真的会被 IPC 代码替换吗?或者它会是普通的图形代码,但以某种方式“加载”到操作系统中,即有一个普遍可访问的运行实例,其他应用程序可以随意调用它?

我知道的一些案例

我知道有很多方法可以解决这个问题,并且知道其中的一些。 但是,所有这些似乎都针对特定的利基市场并且存在缺陷;似乎没有一个足够全面来解释现代应用生态系统令人难以置信的功能(关于操作系统和应用服务的互连性)。

例如:

  • 在过去 (DOS) 时代,我相信 app <-> OS 通信是通过系统中断完成的。
  • 在 UNIX 世界中,这是通过控制台上的 stdin/stdout 管道和 X Windows 中的网络协议完成的。
  • 在 Windows 和 Linux 上有像 COM+/DCOM/DCOP/DBus 这样的 IPC 平台,但同样,这些平台似乎是针对特定目的(大规模构建和管理组件;当今 SOA 的前身)。李>

问题

还有哪些其他方式可以促进这种交流?或者,更具体地说,传统意义上的“这是如何完成的”,尤其是在涉及操作系统 API 时?

一些更具体的问题示例:

  • 内核如何在启动时“加载”设备驱动程序,该驱动程序运行自己的代码(在隔离空间中?)但仍与它上面的内核通信,该内核当前在内存中运行?这种沟通是如何发生的?

  • 应用程序如何与窗口子系统(使用套接字的 X 和 Quartz 除外)通信?我认为 WIN32 使用了中断(也许它仍然使用?),但是新的东西是如何工作的呢?我会非常惊讶地发现,即使在今天,像 WPF 或 Metro 这样的复杂框架仍然归结为调用中断。我实际上不确定这些系统是否使用了 WIN32 API。

  • GDI+ 和 Linux 帧缓冲区等较低级别的图形子系统呢?

注意:我认为在 WIN32(可能还有 GDI+)的情况下,你会得到一个指向上下文的指针(句柄),所以这个概念实际上是“共享内存”。但就这么简单吗?仅获取指向原始资源的原始指针似乎很不安全。意思是,有些东西可以保护你不向这个指针写入任意数据,所以我认为它比这更复杂。

  • (这可能与特定于 JVM 的内容有点脱节)在应用程序服务器中运行的 servlet 如何与实际的应用程序服务器通信?意思是,它们如何在当前运行的服务器的“上下文中”加载自己?

  • 关于 IIS 的同样问题 - 管道设置究竟如何使 IIS 可以控制并与运行 ASP.NET 应用程序的单独进程来回通信?

注意:我不确定这个问题是否有意义,并且可能是愚蠢的或措辞不佳。但是,我希望我的观点能够得到理解,并且当涉及到这些场景(如果有这样的事情)时,具有系统背景的人可以加入标准的“做事方式”。 p>

编辑:我并不是要一份详尽的 IPC 方法列表。我正在尝试找出一个特定的概念,但我不熟悉正确的术语,因此很难找到单词来确定它。这就是为什么这个问题有这么多例子,以“消除”问题没有针对的部分。

【问题讨论】:

  • 它非常广泛,每个问题都可以通过简单的网络搜索找到很多答案和解释。
  • @SamiKuhmonen 我知道用于在没有 Google 的情况下完成此任务的“技术”的高级描述。这就是为什么我在我的问题中列出它们。但是,基本原理并不是我在任何地方都能找到的。
  • 每种语言都有自己的编译器/运行时环境,通过使用底层操作系统的系统调用与操作系统进行交互。我不是专家,但是这个问题在这里无法回答,因为它是(too)^n broad,其中 n-> 一个非常大的值。我希望这一点本身就足以让您开始在 Google/web 上搜索。
  • @Am_I_Helpful 我知道第一点;我的问题更多是关于没有复杂运行时的语言(或者,在这些语言的情况下,如何在运行时中设置实际的管道。大多数(如果不是全部)这些运行时仍然归结为 C API 调用)。另外,我认为可以有一个答案;我在帖子中提供示例的原因是试图将其缩小到我正在谈论的特定概念(我不知道它的名称,因此帖子这么长)
  • @BasileStarynkevitch 有趣...实际上,我认为这是人们在任何本科操作系统课程中都会学到的东西(我从未上过,所以我不知道),这就是为什么我很尴尬甚至问这个。但是不,您可以了解 Windows 的工作原理。在微软于 2006 年将其收购并任命他为 Azure 的首席技术官之前,Mark Russinovich 实际上建立了一家完整的公司 (WinInternals)。

标签: operating-system system ipc computer-architecture internals


【解决方案1】:

问题太笼统,但有几点(与Linux有关;Windows的原理应该相同,但您可能被禁止全部理解):

基本system calls(在syscalls(2)...中列出的那些)由基本machine instruction(例如SYSENTERSYSCALL)调用,它将处理器切换到内核mode(与系统调用号和参数通过定义的寄存器传递,遵循ABI 约定)。因此,用户空间代码可以被视为在某些 virtual machine 中运行(由用户模式指令 + 系统调用原语定义)。顺便说一句,Linux 内核可以将kernel modules 加载到例如在其中添加额外的代码(例如设备驱动程序),这也是通过系统调用完成的。

inter-process communication 设施构建在这些系统调用之上(可能由标准库在更高级别的函数中使用,例如,getaddrinfo(3) 可能间接与某些DNS 服务交互,请参阅@987654331 @)。阅读Advanced Linux Programming 了解更多详情。在实践中,您将需要几个server 程序(并且这个想法在microkernel 方法中被推到了极致),尤其是(在最近的Linux 上)systemd。驱动程序和内核模块由特定的系统调用加载,后来成为内核的一部分,因此可以通过其他系统调用使用。与strace(1) 一起玩,以了解某些 Linux 程序完成的实际系统调用。一些信息由内核通过伪file systems(参见proc(5)...)通过系统调用访问。

从用户程序到内核的每一次通信都是由 IPC 完成的(由系统调用实现)。有时,内核会向上调用用户代码(在 Linux 上,使用 signals)。

Linux 帧缓冲区(以及物理键盘和鼠标)通常只能由单个服务器访问,其他桌面应用程序使用通常的 IPC 设施与之通信 -sockets-,该服务器是 X11Wayland 服务器.

还可以阅读一些关于Operating Systems 的好书,例如可免费下载的Operating Systems: Three Easy Pieces

对于 Windows、MacOSX、Android,它非常相似。但是,由于 Windows (etc...) 是 proprietary software,因此您可能无法了解所有详细信息(并且您可能不被允许 reverse-engineer 它们)。相比之下,Linux 是free software,所以你可以研究它的源代码。

我的建议是详细了解 Linux 的工作原理(这需要几年时间)并研究一些相关的源代码(这对于免费软件来说是可能的)。如果您需要深入了解 Windows,您可能需要购买它的一些源代码许可证(可能是数百万美元)并签署 NDA。我根本不了解 Windows,但 AFAIK 仅由 C 中的一个巨大的API 定义。谣言说 Windows 内核类似于微内核,但微软有经济利益隐藏丑陋的实现细节。

另见osdev

【讨论】:

  • 谢谢!这是一个好的开始。是的,我认为syscalls 背后的机制本质上是中断(至少根据维基百科的文章),我在问题中提到了这一点。 Windows 非常相似。但是这种机制更多的是用于流程管理。我对图形和窗口管理等更复杂的任务如何实际发生更好奇。 (嗯,我知道在 X 中它是通过套接字,而在老式 WIN32 中它也是基于中断的。但我并不真正了解它在更现代的系统中是如何工作的)。
  • 系统调用用于每个 IPC,没有例外(至少在Linux上)
  • 包括驱动程序/内核模块?
  • 驱动程序和内核模块在内核内部,但是它们被加载然后被系统调用使用;顺便说一句,Linux/x86-64 系统调用不使用中断,而是使用 SYSCALL 机器指令
  • 那么模块是如何在运行时加载的呢?加载请求是否会触发对内核的调用,从而拉入模块?或者它是执行代码以将自身加载到内核中的模块? (抱歉,不确定这是否有意义)
猜你喜欢
  • 2012-03-11
  • 2014-02-05
  • 2022-01-05
  • 2012-03-28
  • 2010-11-16
  • 1970-01-01
  • 2014-06-20
  • 2013-08-29
  • 2015-11-28
相关资源
最近更新 更多