`
helloyesyes
  • 浏览: 1272328 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

进程间通信(一)

阅读更多

第13章 进程间通信:管道

在第11章,我们了解了使用信号在两个进程之间发送消息的一个简单方法。我们创建了可以用来引起响应的通知事件,但是所传递的信息限制于一个信号数量。

在这一章,我们将会了解管道,这会允许在进程之间交换更为有用的数据。在本章的结尾,我们将会使用我们的新知识来重新将CD数据库程序实现为一个非常简单的客户/服务器程序。

在本章,我们将会涉及下列主题:

管道的定义
处理管道
管道调用
父子进程
有名管道:FIFO
客户端/服务器方法

什么是管道?

当我们由一个进程到另一个进程连接数据流时我们使用术语管道。通常我们将一个进程的输出连接到另一个进程的输入。

大多数Linu用户已经很熟悉将shell命令连接到一起的思想,从而一个进程的输入可以直接连接到另一个进程的输入。对于shell命令,这是用下面的方式来输入的:

cmd1 | cmd2

shell安排标准输入与两个命令的输出,从而
cmd1的标准输入来自由终端键盘
cmd1的标准输出作为标准输入连接cmd2
cmd2的标准输出连接到终端屏幕

实际上,shell所完成的工作就是重新连接标准输入与输出流,从而由键盘输入的数据流可以通过两个命令,然后输出到屏幕。下图是这个过程的一个可视化表示。

在这一章,我们将会了解如何在一个程序中实现这种效果,以及我们如何使用管道来连接多个进程从而使得我们实现一个简单的客户端/服务器系统。

处理管道

也许在两个程序之间传递数据最简单的方法就是使用popen与pclose函数了。这两个函数原型如下:

#include <stdio.h>
FILE *popen(const char *command, const char *open_mode);
int pclose(FILE *stream_to_close);

popen

popen函数允许一个程序调用另一个程序作为一个新的进程,并且或者向其发送数据或者由其接收数据。command字符串是要运行的程序名字及其参数。open_mode必须或者是"r"或者是"w"。

如果open_mode是"r",由被调用程序的输出可以为调用程序所用,并且可以使用通常的stdio库函数中用于读取的函数由popen函数所返回的文件流 FILE *中进行读取。然而,如果open_mode是"w",程序可以使用fwrite调用向被调用的程序发送数据。被调用的程序可以由其标准输入读取数据。通常,正被调用的程序并不会知道他正在由另一个进程读取数据;他只是简单的读取其标准输入流。

popen调用必须指明是"r"或者是"w";在popen的标准实现中并不支持其他的选项。这就意味着我们不能调用另一个程序,同时由其读取并向其写入。一旦失败,popen就会返回一个空指针。如果我们希望使用管道进行双向通信,通常的解决方法是使用两个管道,每个方向用于一个数据流。

pclose

当由popen所启动的进程已经完成时,我们可以使用pclose来关闭与其相关的文件流。pclose调用只会在由popen所启动的进程完成时才会返回。如果当调用pclose时,这个进程仍在运行,pclose调用就会等待这个进程结束。

pclose调用通常返回他正关闭的进程的文件流的返回的代码。如果调用在调用pclose之前已经执行了一个wait语句,返回状态就会丢失,而pclose就会返回-1,并且将errno设置为ECHILD。

试验--读取另一个程序的输出

下面我们来试验一个简单的popen与pclose的例子,popen1.c。我们会在一个程序中使用popen来访问uname所输出的信息。uname -a命令输出系统信息,包括机器类型,OS名字,版本号以及机器的网络名。

在初始化程序之后,我们打开一个连接uname的管道,使其可读并且设置read_fp指向输出。最后,由read_fp指向的管道会被关闭。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main()
{
FILE *read_fp;
char buffer[BUFSIZ +1];
int chars_read;
memset(buffer,'\0',sizeof(buffer));
read_fp = popen("uname -a","r");
if(read_fp != NULL)
{
chars_read = fread(buffer,sizeof(char),BUFSIZ,read_fp);
if(chars_read > 0)
{
printf("Output was:-\n%s\n",buffer);
}
pclose(read_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}

当我们运行这个程序,我们就会得到下面的输出:

$ ./popen1
Output was:-
Linux gw1 2.4.20-8 #1 Thu Mar 13 17:54:28 EST 2003 i686 i686 i386 GNU/Linux

工作原理

这个程序使用popen调用来调用带有-a参数的uname命令。他然后使用所返回的文件流来读取直到BUFSIZ个字符然后输出到屏幕上。因为我们在一个程序内部捕获uname输出的,所以他可以用来处理。

向popen发送输出

现在我们已经看到由一个外部程序捕获输出的例子,下面我们来看一下向另一个程序发送输出。这就是popen2.c,将数据导向另一个管道。在这里我们将使用od(octal dump)。

试验--向外部程序发送输出

看一下下面的代码,如果我们愿意可以将其输入文本编辑器。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main()
{
FILE *write_fp;
char buffer[BUFSIZ +1];

sprintf(buffer,"Once upon a time, there was...\n");
write_fp = popen("od -c","w");
if(write_fp != NULL)
{
fwrite(buffer,sizeof(char),strlen(buffer),write_fp);
pclose(write_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}

当我们运行这个程序时,我们会得到下面的输出:

$ ./popen2
0000000 O n c e u p o n a t i m e
0000020 , t h e r e w a s . . . \n
0000037

工作原理

这个程序使用带有"w"参数的popen调用来启动od -c命令,从而他可以向这个命令发送数据。然后他发送一个字符串,od -c命令可以接收并处理;od -c命令然后在其标准输出上输出其处理结果。

在命令行上,我们可以使用下面的命令来得到同样的结果

$ echo “Once upon a time, there was...” | od -c

分享到:
评论

相关推荐

    linux进程间通信与同步.pdf

    Linux系统中的进程间通信是典型的虚拟内存系统中的进程间通信:Linux 的进程间通信是不同进程间交换数据的机制。由于Linux系统支持虚拟内 存, 对于每一个进程,系统会为它分配一个单独的进程空间,不同的进程有不同...

    进程间通信

    七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四.信号 ( sinal ) 五.消息队列 ( message queue ) 六.信号量 ( semophore ) 七.套接字 ( socket ) 进程间通信...

    C# 进程间通信 共享内存

    共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。...1、进程间通信 2、共享内存 3、托管方式与非托管共享内存

    进程间通信之信号 sinal ) 完整代码

    进程间通信之信号 sinal ) 唯一的异步通信方式 七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 sinal 五 消息队列 message queue ) 六 信号量 ...

    深入理解Linux进程间通信

    Linux环境进程间通信(一) 3 Linux环境进程间通信(二): 信号(上) 19 Linux环境进程间通信(二): 信号(下) 30 Linux环境进程间通信(三) 40 Linux环境进程间通信(四) 52 Linux环境进程间通信(五): 共享...

    UNIX网络编程_卷2_进程间通信

    卷2:进程间通信(第2版)》是一部UNIX网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。《UNIX网络编程.卷2:进程间通信(第2版)》从对...

    进程间通信之套接字( socket )——完整代码

    进程间通信之套接字( socket ) 网络间通信 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四.信号 ( sinal ) 五.消息队列 ( message queue ) 六.信号量 ( ...

    进程间通信例子

    进程间通信,可以在winform下两个进程,收信息,发信息。很实用的一个例子。

    socket 实现进程间通信

    实现三个进程用socket完成进程间通信。用到socket 的本地通信,与select()函数,信号,还有在一个进程中完成另外一个进程的重新启动

    socket进程间通信的一个一对多例子

    参考网络编写的一个socket通信的例子,可以实现一个服务器对多个客户端,可以用来网络间或进程间通信,参考

    android 进程间通信demo

    一个简单的进程间通信

    AIDL进程间通信demo

    这是一个简单的进程间通信的demo

    linux进程间通信详解

    很详细的介绍linux下进程间通信的书籍.很值得一看的书.

    C# 使用管道Pipe在进程间通信

    进程间通信的一种方式,Pipes:管道,分为无名管道:在父子进程间交换数据;有名管道:可在不同主机间交换数据,分为服务器方和客户方,在Win9X下只支持有名管道客户。 1、进程间通信 2、管道Pipe通信

    进程间通信动态链接库

    这个一个非常简单、非常实用的进程间通信的动态库,使用起来只需要派生个子类就可以了。经过了三个项目的考验。提供在线帮助!使用起来比SOCKET简单该类的实现都以封装在了DLL中,只需要简单的调用提供接口就可以...

    进程间通信之消息队列 ( message queue )——完整代码

    进程间通信之消息队列 ( message queue ) 消息队列是消息的链表,具有特定的格式,并由消息队列标识符标识. 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四....

    QT之进程和进程间通信(IPC)

    进程是操作系统的基础之一。一个进程可以认为是一个正在执行的程序。我们可以把进程当做计算机运行时的一个基础单位。关于进程的讨论已经超出了本章的范畴,现在我们假定你是了解这个概念的。 在 Qt 中,我们使用...

    四种进程间通信的方式demo

    四种进程间通信的方式:activity 、service AIDL 、ContentProvider 、BroadcastReceiver 一个客户端一个服务端,相互通信

    C#使用SendMessage实现进程间通信的方法

    本文实例讲述了C#使用SendMessage实现进程间通信的方法。分享给大家供大家参考。具体分析如下: 为了深入理解消息机制,先来做一个测试项目 在新建项目的Form1的代码中,加入方法: protected override void ...

    进程间通信之无名管道(pipe) 完整代码

    进程间通信之无名管道(pipe) 注意: 1 只能用于具有亲缘关系的进程之间的通信 2 SIGPIPE信号的处理 七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 ...

Global site tag (gtag.js) - Google Analytics