2014 年 1 月 9 日更新:TL;DR 版本: 转到这篇文章的底部以获取让 Cygwin 能够调用非 Cygwin 程序的方法。
在花时间制作了一些碰巧很大的 bash 脚本之后,较新版本的 Cygwin 已经破坏了它们。这些脚本调用不与 Cygwin 链接的本机 Win32 应用程序,这显然不受 Cygwin 的官方支持。
这让我感到惊讶,因为多年来我一直认为 Cygwin 可以在一个更加混合的环境中使用,该环境结合了本地非 Cygwin Win32 应用程序和使用 Cygwin 兼容层的 POSIX 程序。但显然只有 POSIX 兼容层真正得到支持,如果本机 Win32 非 Cygwin 应用程序工作,那么这被认为是一个快乐的巧合。
我从 Cygwin 中运行的针对 .NET Framework 编译的程序遇到的不兼容问题中发现了这一点。这曾经工作得很好,但几个月前就坏了。具体来说,通过管道传输到任何其他 Win32 程序标准输入的 .NET 程序的标准输出通常会导致接收 Win32 程序获得过早的文件结束信号,因为几个月前 Cygwin 最近从字节管道切换到消息管道- 并且消息管道似乎与任何使用 Visual C++ 或 .NET Framework 的接收应用程序不兼容。这是因为 .NET 向标准输出发出空写入,仅在使用消息管道时才将其传递给接收应用程序。接收应用程序成功读取零字节,因此认为它是文件结尾。项目负责人不
从邮件列表中的多封电子邮件中引用项目负责人 Christopher Faylor 的话:
您所看到的可能是因为 Cygwin 在几次修订前被更改为使用消息类型管道。这不会改变。采用该更改是为了解决 Cygwin 程序的问题,而这些显然是我们的第一要务。
无论有多少人使用 Visual C++ 或 .NET,他们都不是我们的目标受众。对于不想使用 UNIX 工具但它们不是我们主要关注点的人来说,这很好。为想要使用非 Cygwin 东西的人解决问题并不是我认为的高优先级。
来自 pipe.cc:请注意,管道的写入端以 PIPE_TYPE_MESSAGE 的形式打开。这似乎更接近于模拟 Linux 管道行为,并且对于 pty 处理肯定是必需的,因为 fhandler_pty_master 以块的形式写入管道,在指定 CANON 模式时由换行符终止。
上面的评论在这里显示了“和”的关系。消息类型管道更接近地模仿 Linux (UNIX) 管道行为,并且绝对是 pty 所必需的。
我同意 James 的观点,即运行时可能有问题,但我也同意 cygwin 应该能够处理这些场景。
你们之间的完全协议不会产生太大的影响。Cygwin 源代码不会因投票而改变。
即使这个问题最终以某种方式得到解决——谁知道呢——他们可能会在 3 个月内破坏其他东西,并且不关心修复回归。他们可能会考虑一个补丁,但我需要很长时间才能找出可行的方法。我认为我的时间最好花在其他地方,因为很明显他们非常愿意破坏与本机 Win32 应用程序的兼容性,并且不想浪费更多时间让 Win32 应用程序正常工作。所以我猜 Cygwin 不应该被认为是混合 Win32/Cygwin 环境的稳定平台——我的选择是什么?我应该从哪里开始以避免完全重写为 bash 以外的东西?我只使用基本 Cygwin 安装 + 一些基本 perl 脚本。
更新: 发布这个原始问题后,他们最终pipe_byte
在环境变量中做了一个新标志CYGWIN
:查看文档。如果设置了这个标志,它将解决上面讨论的问题。调用非 Cygwin Win32 程序时,请始终确保pipe_byte
设置了标志。
但是,我后来发现与 .NET Framework 4.0 和 Cygwin 不兼容。.NET Framework 的早期版本没有此问题。我首先在 Cygwin 邮件列表中提到了这个问题:
Cygwin 和 .NET Framework 4.0 之间的管道同步和不兼容
没有得到任何有效的回应,我进一步调查发现 Cygwin 正在创建重叠管道,这导致了问题。请注意,尝试对重叠管道使用非重叠 Win32 API 调用是未定义的,并且大多数(全部?)Win32 非 Cygwin 程序不使用标准文件句柄的重叠 I/O。我提交了一个补丁,该补丁在环境变量中创建了一个pipe_nooverlap
标志,以CYGWIN
防止这种情况发生:
不幸的是,他们拒绝了这个补丁,所以你永远不会在主 Cygwin DLL 中看到这个:
拒绝补丁的理由:
- 暗示我破坏了 Cygwin 中的信号实现;我没有发现这种情况,因为信号仍然使用重叠的管道。
- 他们不想添加环境变量标志,即使它显然是在解决问题。
- 他们不想支持甚至可以选择使用非重叠管道的代码。
以这样的推理和态度,恐怕我想不出任何办法来更改补丁以适应他们的要求……他们似乎决心禁止使用非重叠管道。我已经使用该补丁一段时间了,并且没有遇到任何问题。另外,我想不出pipe_nooverlap
标志会破坏的任何情况(请参阅我在他们的邮件列表上的后续电子邮件),但我将其作为标志留下以防万一出现麻烦。
因此,如果要从 Cygwin 调用非 Cygwin Win32 或 .NET Framework 程序,则需要执行以下操作:
- 将我的补丁应用到您使用的任何 Cygwin 版本的源代码中。不要期望这个补丁会出现在未来的 Cygwin 版本中。
- 在环境变量中设置
pipe_byte
和pipe_nooverlap
标志。CYGWIN
这工作......现在!我发布这个以防它帮助其他仍然想在某些事情上使用 Cygwin 的人。