- 引言:
- 最近在看一本关于计算机操作系统的书,有一章节讲的内容是程序的进程。
- 程序的进程之间有三种通信机制:1.共享存储器系统 2.消息传递系统 3.管道通信
- 其中消息传递系统是当前应用最为广泛的一种通信机制。熟悉WINDOWS编程的朋友应该不会陌生。
- 书中短短一小段话就把管道通信介绍完毕,可见这部分内容并不是非常重要。
- 但是我却对管道通信起了兴趣,想起了CMD下的管道命令,我决定深入了解一番。
复制代码 我们先来了解什么是管道,书中是这样定义的:
所谓“管道”,是指用于连接一个读进程和一个写进程以实现他们之间通信的一个共享文件,又名pipe文件。
在这里,许多人会这样想,“一个文件?那不是硬盘上找的到,在什么位置呢?”
我先跟大家提一下,管道“文件”是由API函数CreateFile创建的,
管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,
它不属于某种文件系统(如FAT32,NTFS,ext3),而是自立门户,单独构成一个文件系统,并且只存在于内存中。
这很类似系统的“设备文件”,所以大家把“管道文件”当作一个缓冲区就可以了。
管道的命名必须遵循特定的命名方法,就是 "\\.\pipe\管道名",当作为客户端的进程要使用时,使用"\\计算机名\\pipe\管道名" 来打开使用。
按照管道的类别分有两种管道,匿名的和命名的;按照管道的传输方向分也可以分成两种,单向的双向的。
根据管道的特点,命名管道通常用在网络环境下不同计算机上运行的进程之间的通信(当然也可以用在同一台机的不同进程中)它可以是单向或双向的;
而匿名管道只能用在同一台计算机中,它只能是单向的。匿名管道其实是通过用给了一个指定名字的有名管道来实现的。
在编程方面的知识我就不扯太多了,有兴趣请自己研究,我在文章结尾会附上参考文档。
CMD下的管道命令 "|" 就是匿名管道。
在CMD下运行:- set input=empty
- echo test | set /p input=
- echo %input%
复制代码
- C:\Users\Broly>set input=empty
-
- C:\Users\Broly>echo test | set /p input=
-
- C:\Users\Broly>echo %input%
- empty
复制代码 结果显示的是empty,也就是说第二行的语句好像是没有赋值成功的。
再来看看这个代码:- set input=empty
- echo test | (set /p input= & set input)
- echo %input%
复制代码
- C:\Users\Broly>set input=empty
-
- C:\Users\Broly>echo test | (set /p input= & set input)
- input=test
-
- C:\Users\Broly>echo %input%
- empty
复制代码 结果显示,管道后面的变量input事实上是被赋值成功的。
那为什么第三条语句会显示input变量的值为empty呢?
因为管道命令 "|" 后面的语句,CMD会新创建一个子进程,
第二句的input实际为一个新的CMD进程里面的变量,
而第三句的input为父进程的变量,所以两个变量的值就不同。
值得注意的是,管道命令 "|" 后面的命令不管是内部命令还是外部命令,CMD都会为其创建新的子进程。
conset工具的实现原理应该就是获取另一个进程的结果再赋值给当前进程的变量。
关于重定向命令:- stdin是标准输入,stdout是标准输出,stderr是标准错误输出。
- 大多数的命令行程序从stdin输入,输出到stdout或stderr,有时我们需要重定向stdout,stderr,stdin。
-
- 在Windows编程中,重定向需要用到管道(Pipe)的概念。管道是一种用于在进程间共享数据的机制。一个管道类似于一个管子的两端,一端是写入的,一端是读出的。由一个进程从写入端写入、另一个进程从读出端读出,从而实现通信,就向一个“管道”一样。
-
- 重定向的原理是:
-
- 首先声明两个概念:主程序(重定向的操纵者)、子进程(被重定向的子进程)
-
- 如果要重定位stdout的话,先生成一个管道, 管道的写入端交给子进程去写,主程序从管道的读出端读数据,然后可以把数据写成文件、显示等等。重定向stderr和stdout是相同的。
-
- 同理,要重定向stdin的话,生成一个管道, 管道的写入端由主程序写,子进程从管道的读出端读数据。
复制代码 大概重定向命令和管道命令的过程就是这样,不是很难理解。
以上部分文字是我直接网上复制过来的,有错误的地方望给予指出。
参考资料:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365781(v=vs.85).aspx |