是否可以为 Windows (Win32) 编写 libPOSIX,而不需要始终加载的后台服务或 DLL?
我了解 Cygwin,也知道它的缺点。我也知道 fork 的速度很慢,但不知道为什么无法解决这个问题。我还知道 Cygwin 需要 DLL。我还了解 POSIX 定义了整个环境(shell 等),这并不是我真正关心的。
我的问题是询问是否有其他方法来解决这个问题。我看到 MinGW 项目正在实现越来越多的 POSIX 功能,但是没有完整的解决方案提供成熟的(与 Linux/Mac/BSD 实现状态相比)POSIX 功能。
这个问题实际上可以归结为: 能否有效地使用 Win32 API(从 MSVC20 开始??)在 Windows API 上提供完整的 POSIX 层?
也许这将成为一个完整的 libc,仅利用操作系统库来实现文件系统访问、线程和进程控制等低级功能。但我不知道 POSIX 到底还包含什么。我怀疑库能否将 Win32 转变为 POSIX 兼容实体。
I know about Cygwin, and I know of its shortcomings. I also know about the slowness of fork
, but not why on Earth it's not possible to work around that. I also know Cygwin requires a DLL. I also understand POSIX defines a whole environment (shell, etc...), that's not really what I care about here.
My question is asking if there is another way to tackle the problem. I see more and more of POSIX functionality being implemented by the MinGW projects, but there's no complete solution providing a full-blown (comparable to Linux/Mac/BSD implementation status) POSIX functionality.
The question really boils down to:
Can the Win32 API (as of MSVC20??) be efficiently used to provide a complete POSIX layer over the Windows API?
Perhaps this will turn out to be a full libc that only taps into the OS library for low-level things like filesystem access, threads, and process control. But I don't know exactly what else POSIX consists of. I doubt a library can turn Win32 into a POSIX compliant entiity.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
POSIX<> Win32。
如果您尝试编写面向 POSIX 的应用程序,为什么不使用 *N*X 的某些变体?如果您更喜欢运行 Windows,您可以在 PC/笔记本电脑等上的 Hyper-V/VMWare/Parallels/VirtualBox 中运行 Linux/BSD/任何内容。
Windows 曾经有一个与 Win32 子系统一起运行的 POSIX 兼容环境,但在 NT4 之后由于缺乏需求而停止。 Microsoft 收购了 Interix 并发布了 Services For Unix (SFU)。虽然 SFU 3.5 仍然可供下载现已弃用,不再开发或支持。
至于为什么 fork 如此慢,您需要了解 fork 不仅仅是“创建一个新进程”,它是“创建一个新进程(本身是一个昂贵的操作),它是调用进程以及所有内存的副本” 。
在 *N*X 中,分叉进程被映射到与父进程相同的内存页面(即相当快),并且仅当分叉进程尝试修改任何共享页面时才会给出新页面。这称为写入时复制。这在很大程度上是可以实现的,因为在 UNIX 中,父进程和分叉进程之间不存在硬障碍。
另一方面,在 NT 中,所有进程都被 CPU 硬件强制执行的屏障分隔开。在 NT 中,生成可以访问进程内存和资源的并行活动的最简单方法是创建线程。线程在创建进程的内存空间内运行,并且可以访问该进程的所有内存和资源。
您还可以通过各种形式的 IPC、RPC、命名管道、邮件槽在进程之间共享数据内存映射文件,但每种技术都有其自身的复杂性、性能特征等。阅读此了解更多详细信息。
因为它试图模仿 UNIX,所以 CygWin 的“fork”操作创建一个新的子进程(在其自己的隔离内存空间中),并且必须在新分叉的子进程中复制父进程中的每个内存页。这可能是一项成本非常高的操作。
再次强调,如果您想编写 POSIX 代码,请使用 *N*X,而不是 NT。
POSIX <> Win32.
If you're trying to write apps that target POSIX, why are you not using some variant of *N*X? If you prefer to run Windows, you can run Linux/BSD/whatever inside Hyper-V/VMWare/Parallels/VirtualBox on your PC/laptop/etc.
Windows used to have a POSIX compliant environment that ran alongside the Win32 subsystem, but was discontinued after NT4 due to lack of demand. Microsoft bought Interix and released Services For Unix (SFU). While it's still available for download, SFU 3.5 is now deprecated and no longer developed or supported.
As to why fork is so slow, you need to understand that fork isn't just "Create a new process", it's "create a new process (itself an expensive operation) which is a duplicate of the calling process along with all memory".
In *N*X, the forked process is mapped to the same memory pages as the parent (i.e. is pretty quick) and is only given new pages as and when the forked process tried to modify any shared pages. This is known as copy on write. This is largely achievable because in UNIX, there is no hard barrier between the parent and forked processes.
In NT, on the other hand, all processes are separated by a barrier enforced by CPU hardware. In NT, the easiest way to spawn a parallel activity which has access to your process' memory and resources, is to create a thread. Threads run within the memory space of the creating process and have access to all of the process' memory and resources.
You can also share data between processes via various forms of IPC, RPC, Named Pipes, mailslots, memory-mapped files but each technique has its own complexities, performance characteristics, etc. Read this for more details.
Because it tries to mimic UNIX, CygWin's 'fork' operation creates a new child process (in its own isolated memory space) and has to duplicate every page of memory in the parent process within the newly forked child. This can be a very costly operation.
Again, if you want to write POSIX code, do so in *N*X, not NT.
这个怎么样
来自 http://en.wikipedia.org/wiki/UWIN
UWIN 环境可能是什么你正在寻找,但请注意它托管在research.att.com,而UWIN是在自由许可证下分发的,它不是GNU许可证。此外,由于它是针对 att 的研究,而且只是他们分发使用的第二个东西,因此文档存在很多问题。
查看更多信息,请参阅我的文章作为 关于 'for ' KornShell 中的循环
嗯,该帖子中的主要 UWIN 链接是错误链接,请尝试
http://www2.research.att.com/sw/download/
另外,您可以查看
或
了解功能与问题。
我希望这有帮助。
How about this
From http://en.wikipedia.org/wiki/UWIN
The UWIN environment may be what you're looking for, but note that it is hosted at research.att.com, while UWIN is distributed under a liberal license it is not the GNU license. Also, as it is research for att, and only 2ndarily something that they are distributing for use, there are a lot of issues with documentation.
See more info see my write-up as the last answer for Regarding 'for' loop in KornShell
Hmm main UWIN link is bad link in that post, try
http://www2.research.att.com/sw/download/
Also, You can look at
OR
To get a sense of the features vs issues.
I hope this helps.
简短回答:否。
“完整的 POSIX” 意味着 fork()、mmap()、signal() 等,而这些在 NT 上[几乎]不可能实现。
为了让大家明白这一点:GNU Hurd 在 fork() 方面也存在问题,因为 Hurd 内核不是 POSIX。
NT 也不是 POSIX。
另一个区别是持久性:
在 POSIX 兼容系统中,可以创建系统对象并将它们留在那里。此类对象的示例包括命名管道和共享内存对象 (shms)。您可以创建一个命名管道或 shm,并将其保留在文件系统(或类似文件系统的特殊位置)中,其他进程将能够访问它。缺点是进程可能会死亡并且无法自行清理,从而留下未使用的对象(您知道僵尸进程吗?同样的事情)。
在 NT 中,每个对象都是引用计数的,并且一旦其最后一个句柄关闭,就会被销毁。文件是少数持久存在的对象之一。
符号链接是一种文件系统功能,并不完全依赖于 NT 内核,但当前的实现(Vista 及更高版本)无法创建与对象类型无关的符号链接。也就是说,符号链接要么是文件,要么是目录,并且必须链接到文件或目录。如果目标的类型错误,则符号链接将不起作用。如果创建符号链接时目标存在,则可以为其指定正确的类型,但 POSIX 要求可以在目标不存在的情况下创建符号链接。我无法想象符号链接的用例首先指向文件,然后指向目录,但 POSIX 说这应该可行,如果不行,则说明您不完全符合 POSIX 标准。或者,如果您的符号链接 API/实用程序可以指定指定正确类型的选项,那么当目标不存在时,这也会破坏 POSIX 兼容性。
可以在某种程度上复制某些 POSIX 功能(例如“单个命名空间中的整数描述符、引用任何 I/O 对象以及可 select() 功能”,而不会牺牲[太多]性能,但这仍然是一项重大任务,而且 POSIX 接口确实具有限制性(也就是说,如果您可以向该函数再添加一个参数,那么就可以做正确的事情...但是您不能,除非你想扔 。
最好的选择是不要依赖难以移植到非 POSIX 系统的 POSIX 功能,或者以较低级别可能针对不同操作系统有单独实现而较高级别不关心的方式进行抽象 关于细节。
Short answer: No.
"Complete POSIX" means fork(), mmap(), signal() and such, and these are [almost] impossible to implement on NT.
To drive the point home: GNU Hurd has problems with fork() as well, because Hurd kernel is not POSIX.
NT is not POSIX too.
Another difference is persisence:
In POSIX-compliant systems it is possible to create system objects and leave them there. Examples of such objects are named pipes and shared memory objects (shms). You can create a named pipe or a shm, and leave it in the filesystem (or in a special filesystem-like place) where other processes will be able to access it. The downside is that a process might die and fail to clean up after itself, leaving unused objects behind (you know about zombie processes? same thing).
In NT every object is reference-counted, and is destroyed as soon as its last handle is closed. Files are among the few objects that persist.
Symlinks are a filesystem feature, and don't exactly depend on NT kernel, but current implementation (in Vista and later) is incapable of creating object-type-agnostic symlinks. That is, a symlink is either a file or a directory, and must link to either a file or a directory. If the target has wrong type, the symlink won't work. You can give it the right type if the target exists when you create the symlink, but POSIX requires that symlinks may be created without their target existing. I can't imagine a use-case for a symlink that points first to a file, then to a directory, but POSIX says that this should work, and if it doesn't, you're not completely POSIX-compliant. Or if your symlinking API/utility can be given an option that specifies the right type, when target doesn't exist, that also breaks POSIX compatibility.
It is possible to replicate some POSIX features to some degree (such as "integer descriptors from in a single namespace, referencing any I/O object, and being select()able" without sacrificing [much] performance, but that is still a major undertaking, and POSIX interface is really restrictive (that is, if you could just add one more argument to that function, it would have been possible to Do The Right Thing...but you couldn't, unless you want to throw POSIX compliance away).
Your best bet is to not to rely on POSIX features that are difficult to port to non-POSIX systems, or abstract in such a way that lower levels may have separate implementations for different OSes, and upper levels do not care about the details.