IBM公司Dr. Edward G. Bradford的一篇文章。
在开始之前,请注意我们对于市场上两种版本的 Windows 称呼将稍有区别。当不需要区分 Windows 2000 和 Windows XP 时将使用“Windows”。当需要区分时,使用“Windows 2000”或“Windows XP”。
管道
管道是一种进程间的通信机制,Windows 和 Linux(以及 UNIX)上都使用的这种机制。 管道源自“贝尔实验室”开发的 UNIX ,并且所有的 UNIX 和 Linux 都继承了这项技术。 管道是通过通常的 IO 接口存取的字节流。 创建管道后,通过使用操作系统的任何读或写 IO 系统调用来读或者写它。在 UNIX 和 Linux 环境中,IO 调用是 read()
和 write()
。 在 Windows 环境中,API 是 ReadFile()
和 WriteFile()
。Windows 管道与 Linux 管道的区别在于 Windows 使用单一句柄(类似于 Linux 文件描述符)支持双向 IO。Linux 管道返回两个文件描述符来实现双向 IO。
Windows 管道
Windows 管道比 Linux 管道复杂得多。Windows 支持命名的和未命名的管道。未命名管道就是接口没有公布其名称的命名管道。Windows 支持管道上的异步 IO,因此单个线程不会阻塞在对管道的 IO 调用。使用异步 IO 这种功能需要不同的 IO 接口。Windows 管道有两种类型:字节型和消息型。字节型管道与 UNIX 管道类似并支持字节流。 在本文中,我不打算研究消息型管道,尽管对于一个完全的比较应该包含它们。Windows 管道用 CreateNamedPipe()
API 来创建。一旦创建, OpenFile()
API 将被用来存取新创建的命名管道的另一端。 管道名位于平面的名称空间。例如, \\.\pipe\anyname
是一个合法的 Windows 命名管道名称。在 C 或 C++ 里名称表示为:
char *pipeAdult = "\\\\.\\pipe\\anyname";
|
只能指定 anyname部分。 要使用 Windows 管道,必须用一个 API 来创建它,用另一个 API 来打开它。下面的示例代码片段显示了这是如何实现的。
创建一个 Windows 命名管道
//
// Create named pipe in Windows
// nbytes -- block size from command line arguments.
//
int mult = 1;
int x;
x = mult*nbytes + 24;
handleA = CreateNamedPipe(pipeAdult,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE,
2, // two connections
x, // input buffer size
x, // output buffer size
INFINITE, // timeout
NULL); // security
if(handleA == INVALID_HANDLE_VALUE) {
printf("CreateNamedPipe() FAILED: err=%d
", GetLastError());
return 1;
}
handleB = CreateFile(pipeAdult,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(handleB == INVALID_HANDLE_VALUE) {
printf("CreateFile() FAILED: err=%d
", GetLastError());
return 1;
}
|
在上述代码片段的第一个可执行行中的数字 24 是用实验方法确定的。我发现 SDK 平台中没有提到它。 如果没有它,程序就无法工作。很明显,在每次向管道写的时候,管道设施需要一个 24 字节的头。
Linux 管道
Linux 管道的创建和使用都要简单一些,唯一的原因是它需要更少的参数。实现与 Windows 相同的管道创建目标,Linux 和 UNIX 使用下面的代码片段:
创建 Linux 命名管道
int fd1[2];
if(pipe(fd1)) {
printf("pipe() FAILED: errno=%d
",errno);
return 1;
}
|
Linux 管道对阻塞之前一次写操作的大小有限制。 专门为每个管道所使用的内核级缓冲区确切为 4096 字节。 除非阅读器清空管道,否则一次超过 4K 的写操作将被阻塞。 实际上这算不上什么限制,因为读和写操作是在不同的线程中实现的。
单线程进程管道的速度
我写了一个程序(pipespeed2.cpp)来测试操作系统管道代码的执行速度。 该程序创建一个管道并读写数据,所有这些都在单一线程中完成。 因为 Linux 在写入器阻塞之前只支持 4K 的写操作,我们的测试以 4K 为块的上限。 生成数的 bash shell 脚本很简单:
生成测试结果的 Bash shell 文件
list="1 2 3 4 6 8 10 12 14 16 20 24 28 32 36 40 44 48 52 56 60 64 72 80 88"
list="$list 96 104 112 120 128 144 160 176 192 208 224 240 256 288 320 352"
list="$list 384 416 448 480 512 576 640 704 768 832 896 960 1024 1280 1536"
list="$list 1792 2048 2560 3k 3584 4k"
uname -s -r
for bytes in $list
do
case $bytes in
----|?k ) count=100k;;
----?|--k) count=100k;;
?|--|--? ) count=500k;;
esac
pipespeed2 $count $bytes
done
|
每次运行的输出被保存到一个文件,并由文本编辑器编辑产生一个可以轻松导入 Microsoft Excel 的文本文件。
编译程序
本文中的程序编译如下:
- Linux: gcc -O2 pipespeed2.cpp -o pipespeed2
- Windows: cl -O2 pipespeed2.cpp
和
- Linux: gcc -O2 pipespeed2t.cpp -lpthread -o pipespeed2t
- Windows: cl -O2 pipespeed2t.cpp
图 1 显示了在随 Red Hat 7.1 交付的 Linux 2.4.2 内核上运行的结果。
图 2 显示了相同的程序编译后在 Windows 2000 Advanced Server 上运行的结果。多数非实质的服务被禁用。
图 3 显示了在新发布的 Windows XP 上运行的结果。
每个测试运行包括 3 个运行(3 个系列)。 正如图表中所看到的,Linux 管道比 Windows 命名管道快很多。Windows XP 命名管道比 Windows 2000 命名管道慢得多。测试中所用的 Windows XP Professional 版本是已发布的“评估版”。
多线程进程管道的速度
Windows 2000 的这些图表示了一种迹象:如果块大小超过 4K,速度还可以进一步提高。为了测试块大于 4K 时的速度,我写了 pipespeed2.cpp 的增强版。 新程序创建了第二个线程。第一个线程写数据,第二个线程读数据。第一个程序的目的是为了理解在支持没有上下文切换开销的环境中与管道的代码路径关联的开销。这是一个人为的环境,也许永远都不会用到。
将 pipespeed2.cpp 的增强版命名为 pipespeed2t.cpp。两个线程将需要来回进行上下文切换以便传输所有数据。因此,第二个程序比第一个多了一项额外的开销 ― 上下文切换。只有在所有数据传输完毕且第二个线程正常终止之后,计时才结束。
图 4、5 和 6 分别显示了 Linux、Windows 2000 和 Windows XP。显然 Windows XP 在命名管道设施上性能大大降低。Linux 轻松地胜过了 Windows 2000,Windows 2000 又轻松地胜过了 Windows XP。
图 4 显示了 pipespeed2t.cpp 的多线程版本在随 Red Hat 7.1 交付的 Linux 2.4.2 内核上运行的结果。它的 IO 速率峰值大约是 700 MB/sec。
图 5 显示了多线程版本在 Windows 2000 上的运行结果。它的 IO 速率峰值大约是 500 MB/sec。
两幅图表显示了相同的形状,但是在块非常大的情况下,Linux 在 100 MB/sec 左右达到了稳定状态。Windows 2000 在同样情况下也达到了稳定状态,但速率只有 80 MB/sec。
图 6 显示了 Windows XP Professional(评估版)上各种线程运行的结果。它的 IO 速率峰值只有 120 MB/sec。
对于所有各种大小的块 Windows XP 都显示了另人失望的结果。也许 论坛上 Microsoft 的某个专家会发表关于如何改进我们的程序以及提高 Windows XP 命名管道性能的有用意见。
由这些简单程序轻松生成的信息,可以告知程序设计者、软件设计师甚至系统管理员关于操作系统的性能。 要避免关于“现实主义”方案无休止的争论,简单是必需的。“简单”应当代表人们写程序的方式。 在这个测试中我没有针对任何平台作特殊的性能优化。
Windows XP 的低性能是另人困惑的。一个可能的解释也许是因为有更好的数据传输方式 ― “套接字”的存在。 我将在以后的专栏里讨论套接字。
Linux 还支持命名管道。对这些数字的早期评论员建议我,为公平起见,应该比较 Linux 的命名管道和 Windows 的命名管道。我写了另一个在 Linux 上使用命名管道的程序。我发现对于 Linux 上命名的和未命名的管道,结果是没有区别。
另一个区别可能在于 Windows 的管道“特性”,它没有固定的缓冲区大小。对于第一个测试,我们把缓冲区大小限定在 4K 以适应 Linux 缓冲区。Windows 所鼓吹的也许就是推荐与 Windows 命名管道相关的缓冲区可以是任意大小的这一好处。要演示任意大小的 Windows 命名管道缓冲区,可以简单地运行一个使用任意块大小的大型单线程程序。我在 Windows 上运行了 pipespeed2.cpp,为它指定了 256 MB 的缓冲区大小。在 ReadFile()
被发出 之前,Windows 承受了增加缓冲区的大小以容纳 256 MB 数据的压力。系统慢得象爬行,我无心等到该操作完成。 这个“特性”是否有用已经很明显了。 然而,对内部缓冲区进行扩大和缩小需要页面分配和重新分配 ― 这些操作通常与简单字节流无关。
结束语
我们编写了两个程序来演示在 Windows 和 Linux 上用管道设施时好的编程实践。第一个程序 pipespeed2.cpp
使用单线程将数据输入输出操作系统来演示管道设施代码路径的性能。第二个程序 pipespeed2t.cpp
用两个线程来传递任意大数量的数据。第二个程序是对管道设施正常用途的更现实的演示。
我们的结果显示 Linux 管道比 Windows 2000 命名管道快很多,而 Windows 2000 命名管道比 Windows XP 命名管道快得多。
分享到:
相关推荐
4. **管道机制**:PowerShell的管道功能允许用户将一个命令的输出作为另一个命令的输入,类似于Unix/Linux中的管道。这种机制极大地提高了命令组合和数据处理的效率。 5. **提供WMI和 CIM 支持**:Windows ...
《深入解析Windows PowerShell 1.0:基于WindowsXP-KB926140-v5-x86-CHS更新》 Windows PowerShell是微软推出的一种强大的命令行接口和脚本语言,它为系统管理员和开发人员提供了更高效、更灵活的方式来管理和自动...
文件“WindowsXP-KB926140-v5-x86-CHS.exe”是针对Windows XP的一个更新补丁,用于添加对PowerShell 1.0的支持。安装这个补丁后,Windows XP用户就可以享受到PowerShell带来的便利。 在Windows XP上安装PowerShell ...
在本课程设计中,我们将设计和实现一个管道通信系统,使用C语言编写,并在Linux操作系统环境下进行实验。我们将使用VMWare软件在Windows XP环境下安装Linux操作系统,并使用GCC编译器编译C语言程序。在实验中,我们...
操作系统中的Windows多线程是计算机程序设计中的一个重要概念,尤其在C++编程中,它允许开发者在同一时间执行多个任务或代码段,提高了程序的效率和响应性。在XP操作系统上,多线程技术被广泛应用于各种应用程序,如...
硬件环境包括运行Windows XP的计算机,通过VMware虚拟机软件安装Linux操作系统。软件环境主要是Linux发行版(如Ubuntu, CentOS等),以及必要的开发工具,如GCC编译器、GDB调试器等。 **四、设计流程** 1. **程序...
* 单用户多任务操作系统:该类操作系统可以支持一个用户和多个任务,如 Windows XP。 * 多用户多任务操作系统:该类操作系统可以支持多个用户和多个任务,如 Linux。 2.1 Linux 的发展及背景 Linux 作为一种开源...
首先,Win32指的是微软Windows操作系统的一个API(应用程序接口),主要适用于32位版本的Windows,如Windows XP、Windows Server 2003等。Win32 API提供了大量函数,开发者可以利用这些函数来创建各种类型的应用程序...
设计报告中提到,学生将在Windows XP环境下,利用虚拟机软件VMware运行Linux操作系统,进行实验和设计。这种方式既能让学生在熟悉的Windows环境下操作,又可以体验到真实的Linux开发环境。通过实践,学生不仅能理解...
- **跨平台能力**:虽然本文档中提到了命名管道最初是为Windows NT设计的,但实际上它在其他操作系统如Linux等也得到了广泛的支持。 - **安全性**:命名管道提供了安全的数据传输通道,可以设置权限控制访问。 - **...
- **双启动安装**:支持 Windows XP 和 Windows 7 系统下安装 Ubuntu,实现双系统共存。 #### 三、初识 Ubuntu - **概览**:Ubuntu 是一款基于 Debian 的流行 Linux 发行版,以其易用性和强大的社区支持著称。 - *...
- **主机操作系统**:Windows XP - **虚拟机软件**:VMware - **目标操作系统**:Linux #### 实验内容与步骤 1. **无名管道通信实现**: - 使用 `pipe()` 系统调用来创建无名管道。 - 通过 `close()` 关闭不需要...
在2.1.1部分,我们了解到这个实验旨在帮助学生回顾并理解不同操作系统的基本概念,如Windows 2000/XP、UNIX和Linux。这些系统广泛应用于各种机构和学校,包括网页服务器。通过对这些系统在实际环境中的使用情况进行...
- **操作系统**: Windows XP - **虚拟机**: 装有Linux操作系统的虚拟机 ### 实验内容与步骤 #### 管道通信机制 管道是一种特殊的进程间通信方式,可以实现一个进程的标准输出到另一个进程的标准输入的连接。管道...
- **实例研究**:书中介绍了Windows2000/XP的同步和通信机制,以及Linux中的信号量机制。 #### 四、存储管理 - **基本功能**:存储管理的主要功能包括内存分配、地址转换、内存保护等。 - **存储管理技术**:传统...