进程与进程间的通信,()实现进程到进程之间的通信

  进程与进程间的通信,()实现进程到进程之间的通信

  在第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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: