序言:这无疑是一个关于计算机体系结构的相当广泛的问题,但我从其他人那里听到并经常对自己感到疑惑。我也不认为对此有直接或快速的答案。但是,我希望精通系统架构的人能够提供一些见解。
一些背景:我主要是一个专注于Web技术和数据库的全栈开发人员。我确实有一些C语言的背景和修补很多低级别的东西,但那是很久以前的事情,而且是非学术性的。因此,我从未深入到OS体系结构中,这是一件让我无法理解的内容。我知道完成这些任务的各种技术和方法(特别是在更高层次上使用适合此目的的技术),但缺乏对低级物流的全面了解/如何发生 - 特别是在操作系统级别的
一般问题是:应用程序如何在"容器内运行?实际上与该容器的运行实例交谈?通过" container",我指的是已经加载到内存中的运行代码的实例(此类代码的示例可以是操作系统,图形绘图界面,应用程序服务器,驱动程序等)。 / p>
此外,此问题仅适用于已编译的代码以及在同一台计算机上运行的系统之间的通信。
让我们说我构建了一个简单的库,其目的是在屏幕上绘制像素。我们还说这个库有一个方法drawPixel(int x, int y)
。
库本身管理自己的绘图上下文(可以是从原始SVGA缓冲区到桌面窗口的任何内容)。使用此API的应用程序只需动态链接到库,并调用drawPixel
方法,而不会在调用后了解库的确切操作。
在幕后,这个drawPixel
方法应该绘制到桌面上的一个窗口,如果它在第一次调用时不存在则创建它。
然而,从技术上讲,如果设置是直截了当的,会发生什么?简单来说,每个调用应用程序都是" pull&运行" drawPixel
中的所有代码及其依赖关系,有效地使每个正在运行的应用程序拥有自己的整个调用链的运行实例(因此,如果它被5个不同的应用程序调用,那么你最终会有5个不同的窗口,而不是一个窗口的共享上下文)。 (我希望我能解释这一点)
所以,我的问题是,这是如何分享"发生在现代操作系统中?
drawPixel
的代码是否真的会被IPC代码替换?或者它是常规图形代码,但不知何故"加载"进入操作系统的方式是有一个普遍可访问的运行实例,其他应用程序随意调用?
我知道有很多方法可以解决这个问题,并且我知道其中的一些方法。 然而,所有这些似乎都解决了特定的利基并且有缺点;似乎没有一个足以解释现代应用生态系统的令人难以置信的功能(关于操作系统和应用服务的互联性)。
例如:
app <-> OS
通过系统中断完成了通信。stdin
/ stdout
管道和X Windows中的网络协议完成的。有什么其他方式可以促进这种沟通?或者,更具体地说,&#34;是如何完成的&#34;在传统意义上,尤其是涉及OS API时?
更具体问题的一些例子:
内核如何加载&#34;启动时的设备驱动程序,它运行自己的代码(在一个隔离的空间?)但仍然与它上面的内核进行通信,该内核当前正在内存中运行?这种沟通是如何发生的?
应用程序如何与窗口子系统(使用套接字的X和Quartz除外)进行通信?我认为WIN32使用了中断(也许它仍然可以吗?),但是新的东西是如何工作的呢?我很惊讶地发现即使在今天,像WPF或Metro这样复杂的框架仍然可以归结为中断。我实际上不确定这些系统是否使用过WIN32 API。
GDI +和Linux Framebuffer等低级图形子系统怎么样?
注意:我认为在WIN32(可能还有GDI +)的情况下,你会得到一个指向上下文的指针(句柄),因此这个概念实际上是#34;共享内存&#34;。但这样简单吗?仅获取原始资源的原始指针似乎非常不安全。意思是,有些东西可以保护你不会将任意数据写入这个指针,所以我认为它比这更复杂。
(由于其特定于JVM,这可能有点脱离上下文)如何在应用程序服务器内运行的servlet与实际的应用程序服务器进行通信?意思是,他们如何在上下文中加载自己&#34;当前正在运行的服务器?
IIS的相同问题 - 管道设置究竟是如何使IIS可以控制和通信的。使用运行ASP.NET应用程序的单独进程?
注意:我不确定这个问题是否有道理,而且可能是愚蠢或措辞不好。但是,我希望我的意见得到解决,并且具有系统背景的人可以使用标准的方式来处理事情&#34;当谈到这些场景时(如果有这样的事情)。
编辑:我不是要求详尽的IPC方法列表。有一个特定的概念,我试图找到,但我不熟悉正确的术语,所以我很难找到指出它的单词。这就是为什么这个问题带有如此多的例子,以及#34;消除&#34;问题没有针对的部分。
答案 0 :(得分:3)
问题太广泛了,但有些问题(与Linux相关; Windows的原则应该是相同的,但你可能无法理解它们):
小学system calls(syscalls(2)中列出的内容)由小学machine instruction(例如SYSENTER
或SYSCALL
)调用处理器进入内核mode(系统调用号和参数通过定义的寄存器传递,遵循ABI约定)。因此,可以将用户空间代码视为在某些virtual machine中运行(由用户模式指令+系统调用原语定义)。顺便说一句,Linux内核可以加载kernel modules到例如在其中添加其他代码(例如设备驱动程序),这也是通过系统调用完成的。
inter-process communication工具建立在这些系统调用之上(可能由更高级别函数中的标准库使用,例如getaddrinfo(3)可能会间接与某些{{3}进行交互 }服务,请参阅DNS)。阅读nsswitch.conf(5)了解更多详情。在实践中,你需要几个Advanced Linux Programming程序(并且这个想法在server方法中被推到极致),特别是(在最近的Linux上)microkernel。驱动程序和内核模块由特定的系统调用加载,后来是内核的一部分,因此可以通过其他系统调用使用。与systemd一起玩,以了解某些Linux程序完成的实际系统调用。内核通过伪strace(1)(参见file systems ...)通过系统调用提供了一些信息。
从用户程序到内核的每次通信都是由IPC完成的(由系统调用实现)。有时,内核正在对用户代码进行上调(在Linux上,使用proc(5))。
Linux帧缓冲区(以及物理键盘和鼠标)通常只能由其他桌面应用程序使用通常的IPC工具进行通信的单个服务器访问 - signals - ,该服务器是sockets或X11服务器。
另请阅读Wayland上的一本好书,例如可免费下载的Operating Systems
对于Windows,MacOSX,Android,它非常相似。但是,由于Windows(等等)是Operating Systems: Three Easy Pieces,您可能无法了解所有细节(并且可能不允许proprietary software这些细节。相比之下,Linux是reverse-engineer,因此您可以研究其源代码。
我的建议是详细了解Linux的工作原理(这需要几年时间)并研究一些相关的源代码(可以使用免费软件)。如果您需要深入了解Windows,您可能需要购买它的一些源代码许可证(可能是数百万美元)并签署NDA。我根本不了解Windows,但AFAIK只是由C中的巨大free software定义。谣言告诉Windows内核是微内核,但微软有经济利益隐藏丑陋的实现细节。
另见API。