Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->网络应用 ->正文

GNU/Linux应用程序编程:用管道进行编程

来源: 作者:Webmaster 时间:2007-12-27 点击: [收藏] [投稿]

简介

在本章当中,我们将学习GNU/Linux管道。管道模型虽然很老但是就算是现在它仍然是一个十分有用的进程间通信机制。我们将会学习什么是半双向管道以及有名管道。它们都提供了一个FIFO(先进先出)排队模型来允许进程间通信。

管道模型

一个形象化管道的描述为——一个在两个实体之间的单向连接器。例如,让我们来看一看下面的这个GNU/Linux命令:

ls -1 | wc –l

这个命令创建了两个进程,一个和ls -l关联而另一个则和wc -l关联。接着它通过设置第二个进程的标准输入到第一个进程的标准输出连接了这两个进程(如图11.1)。产生的结果是——计算了当前子目录的文件数目。

我们的命令设置了一个在两个GNU/Linux命令之间的管道。命令ls被执行之后它产生的输出被用作第二个命令wc(word count)的输入。这是一个单向管道——通信发生在一个方向上。两个命令之间的连接由GNU/Linux来完成。我们也可以在应用程序当中做到这一点(等一下我们将会证明这一点)。

匿名管道和有名管道

一个匿名管道或者说单向管道,为一个进程提供了和它的一个子进程(匿名的种类)进行通信的方法。这是因为没有可以在操作系统当中找到一个匿名进程的方法。它的最通常的用法是在父进程建立一个匿名管道,然后将这个管道传递给它的子进程,然后它们就可以进行通信了。注意,如果需要双向通信的话,我们考虑使用的API就应该是套接字(sockets)API了。

管道的另一种类型是有名管道。一个有名管道其功能和匿名管道差不多,差别就在于它是可以在文件系统中存在的并且所有进程都可以找到它。这意味着没有血缘关系的进程之间可以使用它来进行通信。

在接下来的部分当中我们将会同时学习有名管道和匿名管道。我们将对管道进行一个快速的游览,然后我们就详细地学习管道API以及支持管道编程的GNU/Linux系统级的命令。

旋风式的游览

让我们以一个简单的管道编程的模型的例子来开始我们的旋风式游览。在这个简单的例子当中,我们在一个进程当中创建了一个管道,然后对它写入一个消息,接下来的就是从这个管道当中读取前面写入的消息,然后将它显示出来。

清单11.1: 一个简单的管道例子

1:#include <unistd.h>
2:#include <stdio.h>
3:#include <string.h>
4:  
5:#define MAX_LINE        80
6:#define PIPE_STDIN      0
7:       #define PIPE_STDOUT     1
8:  
9:       int main()
10:       {
11:         const char *string={"A sample message."};
12:         int ret, myPipe[2];
13:         char buffer[MAX_LINE+1];
14:  
15:         /* Create the pipe */
16:         ret = pipe( myPipe );
17:  
18:         if (ret == 0) {
19:  
20:           /* Write the message into the pipe */
21:           write( myPipe[PIPE_STDOUT], string, strlen(string) );
22:  
23:           /* Read the message from the pipe */
24:           ret = read( myPipe[PIPE_STDIN], buffer, MAX_LINE );
25:  
26:           /* Null terminate the string */
27:           buffer[ ret ] = 0;
28:  
29:           printf("%s\n", buffer);
30:  
31:         }
32:  
33:         return 0;
34:       }

在清单11.1当中,我们在16行当中使用了函数pipe创建了我们的管道。我们向函数pipe传入了一个拥有两个元素的代表我们的管道的整型数组。管道被定义为一对分开的文件描述符——一个输入和一个输出。我们可以从管道的一端写入然后从管道的另一端读取。如果管道成功建立的话,API函数pipe就会返回0。基于返回,myPipe将会包括两个新的代表管道的输入(myPipe[1])和对管道的输出(myPipe[0])的文件描述符。(PS: in文件描述符代表其所关联的文件或者设备相当于一个输入设备;out文件描述符则代表其所关联的文件或者设备相当于一个输出设备。)

在21行,我们使用函数write将我们的消息写入管道。我们指定了stdout(标准输出)描述符(这是从应用程序的角度来看的,而非管道)。管道现在包含了我们的消息,然后它能够在24行被函数read读取。在这里我们再次说明一下,从应用程序的角度来看,我们使用了stdin(标准输入)描述符来从管道进行读取。函数read将从管道当中读取到的消息保存到了变量buffer。为了让buffer真正地成为一个字符串,我们在其后添加了一个0 (NULL),然后我们就可以在29行使用函数printf显示它了。

虽然这个例子很有趣,但是我们自己之间的通信的执行可以使用任意数量的机制。接下来我们将要学习提供了进程(不论是有关系的还是无关系的)间通信的更为复杂的例子。

详细的回顾

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:新手学堂:Linux系统下Matlab的安装设置   下一篇:Linux+Apache+PHP+JSP 的Resin解决方案 (1)

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号