进程间通信:管道

什么是管道

当从一个进程连接数据流到另一个进程时,我们使用术语管道(pipe)。我们通常是把一个进程的输出通过管道连接到另一个进程的输入。
大多数Linux的用户应该早已对将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",被调用程序的输出就可以被调用程序使用,调用程序利用popen函数返回的FILE*文件流指针,就可以通过常用的stdio库函数(如fread)来读取被调用程序的输出。如果open_mode是"w",调用程序就可以用fwrite调用向被调用程序发送数据,而被调用程序可以在自己的标准输入上读取这些数据。被调用的程序通常不会意识到自己正在从另一个进程读取数据,它只是在标准输入流上读取数据,然后做出相应的操作。

每个popen调用都必须指定"r"或"w",在popen函数的标准实现中不支持任何其他选项。这意味着我们不能调用另一个程序并同时对它进行读写操作。popen函数在失败时返回一个空指针。如果想通过管道实现双向通信,最普通的解决方法是使用两个管道,每个管道负责一个方向的数据流。

pclose函数

用popen启动的进程结束时,我们可以用pclose函数关闭与之关联的文件流。pclose调用只在popen启动的进程结束后才返回。如果调用pclose时它仍在运行,pclose调用将等待该进程的结束。

pclose调用的返回值通常是它所关闭的文件流所在进程的退出码。如果调用进程在调用pclose之前执行了一个wait语句,被调用进程的退出状态就会丢失,因为被调用进程已结束。此时,pclose将返回-1并设置errno为ECHILD。

实例-读:

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

int main()
{
   
    FILE *read_fd;
    char buff[128] = {
   0};
    int read_count = 0;
    read_fd = popen("uname -a","r");
    if(read_fd != NULL)
    {
      
        read_count = fread(buff,sizeof(char),127,read_fd);
        while(read_count != 0)
        {
      
            printf("read : %s",buff);
            read_count = fread(buff,sizeof(char),127,read_fd);
        }   
        pclose(read_fd);
        exit(EXIT_SUCCESS);
    }   
    exit(EXIT_FAILURE);
}

在这里插入图片描述
这个程序用popen调用启动带有-a选项的uname命令。然后用返回的文件流读取所有数据,并将它们打印出来显示在屏幕上。因为我们是在程序内部捕获uname命令的输出,所以可以处理它。

实例-写:

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

int main()
{
   
    FILE *write_fd;
    char buff[128] = "12 23 34 45 56 67 78 89";
    int write_count = 0;
    write_fd = popen("cat","w");
    if(write_fd != NULL)
    {
      
        
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值