进程与进程间的通信,()实现进程到进程之间的通信
在第11章中,我们学习了使用信号在两个进程之间发送消息的简单方法。我们创建了一个通知事件,可用于引起响应,但传输的信息受到信号数量的限制。
在这一章中,我们将学习管道,它允许更多有用的数据在进程间交换。在本章的最后,我们将使用我们的新知识把CD数据库程序重新实现为一个非常简单的客户机/服务器程序。
在本章中,我们将讨论以下主题:
管道的定义
处理管道
管道调用
父子过程
命名管道:FIFO
客户机/服务器方法
什么是管道?
当我们将数据流从一个进程连接到另一个进程时,我们使用管道这个术语。我们通常将一个过程的输出连接到另一个过程的输入。
大多数Linu用户已经熟悉了将shell命令链接在一起的想法,这样一个进程的输入可以直接连接到另一个进程的输入。对于shell命令,输入方式如下:
命令1 命令2
安排shell的标准输入和两个命令的输出,这样
cmd1的标准输入来自终端键盘。
cmd1的标准输出连接到cmd2作为标准输入
cmd2的标准输出连接到终端屏幕。
实际上,shell所做的是重新连接标准的输入和输出流,使键盘输入的数据流可以传递两个命令,然后输出到屏幕上。下图直观地展示了这一过程。
在本章中,我们将学习如何在程序中实现这种效果,以及如何使用管道连接多个进程,从而实现一个简单的客户机/服务器系统。
也许在两个程序之间传输数据最简单的方法是使用popen和pclose函数。这两个函数的原型如下:
#包含stdio.h
FILE *popen(const char *command,const char * open _ mode);
int p close(FILE * stream _ to _ close);
打开进程文件指针
popen函数允许一个程序调用另一个程序作为一个新的进程,或者向它发送数据,或者从它那里接收数据。命令字符串是要运行的程序的名称及其参数。Open_mode必须是“r”或“w”。
如果open_mode为 r ,则被调用程序的输出可以被调用程序使用,并且可以通过使用通常的stdio库函数中用于读取的函数,从popen函数返回的文件流FILE *中读取。但是,如果open_mode为 w ,程序可以使用fwrite调用向被调用程序发送数据。被调用的程序可以通过它的标准输入读取数据。通常,被调用的程序不知道它正在被另一个进程读取数据;他只是读取它的标准输入流。
Popen调用必须指示“r”或“w”;popen的标准实现不支持其他选项。这意味着我们不能调用另一个程序,同时读取和写入它。一旦失败,popen将返回一个空指针。如果我们想要使用管道进行双向通信,通常的解决方案是使用两个管道,每个方向一个管道。
关闭进程文件指针
当popen启动的进程完成后,我们可以使用pclose关闭与之相关的文件流。只有当popen启动的进程完成时,pclose调用才会返回。如果调用pclose时该进程仍在运行,则pclose调用将等待该进程完成。
pclose调用通常返回它正在关闭的进程的文件流的代码。如果在调用pclose之前调用已经执行了wait语句,那么返回状态将会丢失,pclose将返回-1并将errno设置为ECHILD。
测试读取另一个程序的输出。
我们来尝试一个popen和pclose的简单例子,popen1.c我们将在一个程序中使用popen来访问uname输出的信息。Uname -a命令输出系统信息,包括机器类型、操作系统名称、版本号和机器的网络名称。
初始化程序后,我们打开一个连接到uname的管道,使其可读,并设置read_fp指向输出。最后,read_fp所指向的管道将被关闭。
#包含stdio.h
#包含stdlib.h
#包含字符串. h
#包括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!=空)
{
chars_read=fread(buffer,sizeof(char),BUFSIZ,read _ FP);
if(chars_read 0)
{
printf(输出为:-/n%s/n ,缓冲区);
}
pclose(read _ FP);
退出(EXIT _ SUCCESS);
}
退出(EXIT _ FAILURE);
}
当我们运行这个程序时,我们将得到以下输出:
$ ./popen1
输出为:-
Linux gw1 2 . 4 . 20-8 # 1 2013年3月13日星期四17:54:28美国东部时间2003 i686 i686 i386 GNU/Linux
这个程序使用popen call来调用带有-a参数的uname命令。然后,他使用返回的文件流读取多达BUFSIZ个字符,然后将它们输出到屏幕上。因为我们在程序中捕获uname的输出,所以它可以用于处理。
将输出发送到popen
现在我们已经看到了一个外部程序捕获输出的例子,让我们来看一下将输出发送到另一个程序。这是popen2.c,将数据引向另一个管道。这里我们将使用od(八进制转储)。
测试-将输出发送到外部程序。
看看下面的代码,如果我们愿意,我们可以将它输入到文本编辑器中。
#包含stdio.h
#包含stdlib.h
#包含字符串. h
#包括unistd.h
int main()
{
FILE * write _ fp
char buffer[BUFSIZ 1];
sprintf(缓冲区,“从前,有./n’);
write_fp=popen(od -c , w );
if(write_fp!=空)
{
fwrite(buffer,sizeof(char),strlen(buffer),write _ FP);
pclose(write _ FP);
退出(EXIT _ SUCCESS);
}
退出(EXIT _ FAILURE);
}
当我们运行这个程序时,我们将得到以下输出:
$ ./popen2
0000000 O n c e u p o n a t i m e
0000020,这是我们的工作。/n
0000037
这个程序使用带有 w 参数的popen调用来启动od -c命令,这样他就可以向这个命令发送数据。然后他发送一个字符串,od -c命令可以被接收和处理;然后,od -c命令在其标准输出上输出其处理结果。
在命令行上,我们可以使用以下命令来获得相同的结果
$ echo“从前,有……”od -c
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。