IPC-管道(匿名管道)

管道(Pipe),也被叫做匿名管道,是UNIX系统IPC的最古老、最基本的机制,所以UNIX系统都提供此种通信机制。管道有两个局限性:

  • 最开始它是半双工的(即数据只能在一个方向上流动)。现在,某些系统提供全双工管道,但是为了可移植性,我们应该假定系统不支持全双工。
  • 管道只能在具有血缘关系的两进程之间使用(兄弟进程、父子进程之类具有公共祖先的进程)。

管道是单向的、先进先出、无结构的字节流,它把一个进程的输出和另一个进程的输入连接在一起。

  • 在写进程在管道尾端写入数据,读进程在管道的首端读出数据。数据读出后其他读取进程都不能再读到这些数据。
  • 当进程试图读取一个空管道时,在另一个写入进程未写入数据之前,进程将一直阻塞。管道已经满时,进程再试图将数据写入管道,在别的读取进程没有读取数据之前,写入数据进程将阻塞。

管道的创建
管道基于文件描述符的通信方式,是通过调用pipe函数创建的。

#include<unistd.h>
int pipe(int fd[2]);

调用pipe函数时在内核开辟一块缓冲区(称为管道),它有一个读端,一个写端,然后通过参数传出给用户程序两个文件描述符。fd[0]指向管道的读端,fd[1]指向管道的写端,就像标准输入0,标准输出1是一样的。所以管道在用户程序看起来就像是一个文件,对于它的读写也可以使用普通的read()和write()等函数。但是它不是普通的文件,并不属于其他任何文件系统,只存在于内核的内存空间中。向它读写数据其实是在读写内核缓冲区。
返回值:调用失败返回-1,成功返回0。
管道
管道创建步骤:
使用管道进行通信大致的步骤:
管道通信步骤

  1. 创建管道:父进程用pipe函数创建管道,得到两个指向管道的文件描述符。
  2. 创建子进程:然后父进程fork出一个子进程,子进程继承父进程的文件描述符,也得到两个指向管道的文件描述符。
  3. 确定管道的传输方向(谁是读端,谁是写端):这里父进程关闭读端fd[0],子进程关闭写端fd[1]。实现父进程向管道里写数据,子进程从管道里面读数据。这样就实现了父子进程之间的通信。
  4. 通信:在写进程中调用write()函数,在读进程中调用read()函数
  5. 关闭管道:用close()关闭管道相关文件按。
    运用实例:
    在父进程中写入”i am child!”然后在子进程中读取,并且打印出来。
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main()
{
    pid_t id;
    int fd[2];
    int ret=pipe(fd);
    if(ret<0)
    {
        printf("pipe error!\n");
    }
    if(id=fork()<0)
    {
        printf("fork error!\n");
    }
    else if(id>0)//father
    {
        close(fd[0]);
        int i=0;
        char* mesg=NULL;
        while(i<100)
        {
            mesg="i am child!";
            write(fd[1],mesg,strlen(mesg)+1);
            sleep(1);
            i++;
        }
        close(fd[1]);
    }
    else//child
    {
        close(fd[1]);
        char mesg[100];
        int j=0;
        while(j<100)
        {
        ssize_t s=read(fd[0],mesg,sizeof(mesg));
        mesg[s-1]='\0';
        printf("%s\n",mesg);
        j++;
        }
        close(fd[0]);
    }
    return 0;
}

运行结果:
这里写图片描述

使用管道还有一些限制:
上面说过两个进程通过一个管道只能实现单项通信。比如上例,如果需要子进程写,父进程读就得另外开一个管道。
另外,需要注意有下面几点情况:

  • 当读一个写端已经被关闭的管道时,在管道中所有数据都被读取后,read返回0,表示文件结束。
  • 如果有指向管道写端的⽂件描述符没关闭(管道写端的引⽤计数⼤于0),⽽持有管道写端的 进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
  • 如果有指向管道读端的⽂件描述符没关闭(管道读端的引⽤计数⼤于0),⽽持有管道读端的 进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再 次write会阻塞,直到管道中有空位置了才写⼊数据并返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值