管道

管道是一种古老的IPC通信形式。它有两个特点:

  • 半双工,即不能同时在两个方向上传输数据。有的系统可能支持全双工。
  • 只能在父子进程间。经典的形式就是管道由父进程创建,进程fork子进程之后,就可以在父子进程之间使用了。
  • 进程创建管道,每次创建两个文件描述符来操作管道。
  • 其中一个对管道进行写,另一个对管道进行读操作。

声明

使用popen函数和pclose函数结合来执行系统命令,就用到了管道,它们声明如下:

FILE *popen(const char *command,const char *type);
int pclose(FILE *stream);

#include <unistd.h>
int pipe(int filedes[2]);
  • filedes是一个文件描述符的数组,用于保存管道返回的两个文件描述符。
  • 下标为0是为了读操作而创建打开的,下标为1是为了写操作而创建打开的。
  • 执行成功返回0;失败返回1;

例子

我们看一个简单的使用管道的例子,这里使用了pipe函数来创建管道:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#define MAX_LEN 128
int main()
{
    /*0为读,1为写*/
    int fd[2] = {0}; //描述符
    pid_t pid = 0;
    char line[MAX_LEN] = {0};
    int n = 0;

    /*创建管道,需要传入两个文件描述符*/
    if(pipe(fd) < 0)
    {
        perror("create pipe failed\n");
        return -1;
    }
    /*fork子进程*/
    if((pid = fork()) < 0)
    {
        perror("fork failed\n");
        return -1;
    }
    /*父进程*/
    else if(pid > 0)
    {
        /*关闭管道的写描述符*/
        close(fd[1]);

        /*从管道读取数据*/
        n = read(fd[0],line,MAX_LEN);
        printf("read %d bytes from pipe :%s\n",n,line);

    }
    /*子进程*/
    else
    {
        /*关闭管道的读描述符*/
        close(fd[0]);
        /*向管道写入数据*/
        write(fd[1],"www.yanbinghu.com",sizeof("www.yanbinghu.com"));
    }
    return 0;
}

在程序中,

  • 我们创建了一个管道,父进程关闭了写通道,子进程关闭读通道;
  • 子进程向管道内写入字符串,而父进程从管道中读取字符串并输出。

运行结果:

read 18 bytes from pipe :www.yanbinghu.com