为什么 Microsoft PowerShell 在安装到 Linux 机器上时能够安装 DLL 文件并且仍然有效?是否有一个人们似乎不知道的 Microsoft 内置接口?
这是从以下网址下载二进制 tar 时所下载内容的图像https://github.com/PowerShell/PowerShell
它里面有 .DLL 文件,而不是 .SO 文件。
答案1
是否存在一个人们似乎不知道的 Microsoft 内置界面?
不需要特殊的接口。Linux 上动态链接可执行文件的加载由用户空间库完成(例如,当你运行 ELF 文件时,它通常表示/lib/ld-linux.so.2
为“解释器”),库– 不是内核 – 实际上负责在启动时以及之后通过 dlopen() 加载 .so 文件。
这意味着,任何程序都可以实现自己的可执行文件或库加载器(如果它真的愿意的话)。内核的参与主要是在通用系统调用中,将文件映射到内存中,并在加载器询问时将正确的内存区域标记为“可执行”(mprotect)。(例如,这个用户空间加载器发布以替代已删除的对旧“a.out”格式的内核支持。)
再举一个例子:Wine 是一个明显的非微软项目,它自己也支持加载 PE 格式的 Windows 可执行文件(并允许它们加载 PE 格式的 DLL),这比 PowerShell 存在的时间要长得多。(以前 Wine 的自己的.dll 里面仍然以 ELF 格式存在,但是最近也已将它们完全转换为 PE。)
因此考虑到这一点:
为什么 Microsoft Powershell 在安装到 Linux 机器上时能够安装 DLL 文件并且仍然可以工作?
PowerShell 整体上建立在 .NET 运行时之上,即使在非 Windows 平台上也始终使用 PE/COFF – .NET 运行时有自己的 PE 加载器(与 Wine 非常相似)并且负责处理 .dll 文件格式以及其中的 CLR 字节码。
(此外,尽管这些是 PE 文件,但它们不是普通的“Windows”DLL——请记住,.NET 语言最初并不是直接编译为机器代码的,它是一个类似于 Java 的字节码平台。)
对于 .NET,大多数相关 DLL 不会直接进行特定于操作系统的调用 - 它们位于 .NET“世界”内,并且运行时本身提供抽象层。(它是可能的.NET 代码直接调用外部库,并且这些调用在错误的操作系统上确实会失败。
以前,.exe
无论在什么平台上,即使是主可执行文件也都是 PE 格式的文件。例如,如果您在 GNOME 中安装了 Banshee 音乐播放器(一个用 C#.NET 编写的完全 Linux 原生应用程序),那么您实际上会有一个 /usr/lib/Banshee.exe(一个 PE32 可执行文件)通过 Mono 运行时运行。
(Banshee 在 /usr/bin 中有一个包装脚本来启动它,但 Linux 也具有“binfmt-misc”功能,允许将非 ELF 二进制文件的执行透明地委托给解释器 - 很容易将 Mono 或 Wine 声明为MZ
PE 文件的处理程序。)