匿名管道的四种特殊情况

管道随进程
匿名管道是存在于内存中的特殊文件
特点:
          1.单向
          2.有血缘关系的进程间通信
          3.实现进程间同步
          4.提供“流式服务”



匿名管道的实现:
test.c
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
int main()
{
  int _pipe[2];
  int ret=pipe(_pipe);
  if(ret==-1)
  {
    printf("create pipe error!error code is:%d\n",errno);
    return 1;
  }
  pid_t id=fork();
  if(id<0)   //create fail
  {
    printf("fork error!\n");
    return 2;
  }
  else if(id==0)  //child
  {
    close(_pipe[0]);
    int i=0;
    char* _mesg_c=NULL;
    while(i<100)
    {
      _mesg_c="i am a child!";
      write(_pipe[1],_mesg_c,strlen(_mesg_c)+1);
      sleep(1);
      i++;
    }
  }
  else  //father
  {
    close(_pipe[1]);
    char _mesg[100];
    int j=0;
    while(j<100)
    {
      memset(_mesg,'\0',sizeof(_mesg));
      read(_pipe[0],_mesg,sizeof(_mesg));
      printf("%s\n",_mesg);
      j++;
    }
  }
  return 0;
}

使用管道要注意以下四种情况(假设都是阻塞 I/O操作,没有设置O_NONBLOCK标志)


1、所有指向写端的文件描述符都关闭了,而仍有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样
test1.c
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
  int _pipe[2];
  int ret=pipe(_pipe);
  if(ret==-1)
  {
    printf("create pipe error!error code is:%d\n",errno);
    return 1;
  }
  pid_t id=fork();
  if(id<0)   //create fail
  {
    printf("fork error!\n");
    return 2;
  }
  else if(id==0)  //child
  {
    close(_pipe[0]);
    int i=0;
    char* _mesg_c=NULL;
    while(i<10)
    {
      _mesg_c="i am a child!";
      write(_pipe[1],_mesg_c,strlen(_mesg_c)+1);
      sleep(1);
      i++;
    }
    close(_pipe[1]);
  }
  else  //father
  {
    close(_pipe[1]);
    char _mesg[100];
    int j=0;
    while(j<100)
    {
      memset(_mesg,'\0',sizeof(_mesg));
      int ret=read(_pipe[0],_mesg,sizeof(_mesg));
      printf("%s:code is:%d\n",_mesg,ret);
      j++;
    }
    if(waitpid(id,NULL,0)<0)
    {
      return 3;
    }
  }
  return 0;
}
结果:
     i am a child!:code is:14  (10行)
     :code is:0  (90行)
     
     Program exited normally.

2、如果有指向管道写端的文件描述符没关闭,而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
test2.c:
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
  int _pipe[2];
  int ret=pipe(_pipe);
  if(ret==-1)
  {
    printf("create pipe error!error code is:%d\n",errno);
    return 1;
  }
  pid_t id=fork();
  if(id<0)   //create fail
  {
    printf("fork error!\n");
    return 2;
  }
  else if(id==0)  //child
  {
    close(_pipe[0]);
    int i=0;
    char* _mesg_c=NULL;
    while(i<20)
    {
       if(i<10)
      {
        _mesg_c="i am a child!";
        write(_pipe[1],_mesg_c,strlen(_mesg_c)+1);
      }
        sleep(1);
        i++;
    }
  }
  else  //father
  {
    close(_pipe[1]);
    char _mesg[100];
    int j=0;
    while(j<20)
    {
      memset(_mesg,'\0',sizeof(_mesg));
      int ret=read(_pipe[0],_mesg,sizeof(_mesg));
      printf("%s:code is:%d\n",_mesg,ret);
      j++;
    }
    if(waitpid(id,NULL,0)<0)
    {
      return 3;
    }
  }
  return 0;
}
结果:
     i am a child!:code is:14  (10行)
     :code is:0  (10行)
     
     Program exited normally.
    
3、如果所有指向管道读端的文件描述符都关闭了,这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。
test3.c:
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
  int _pipe[2];
  int ret=pipe(_pipe);
  if(ret==-1)
  {
    printf("create pipe error!error code is:%d\n",errno);
    return 1;
  }
  pid_t id=fork();
  if(id<0)   //create fail
  {
    printf("fork error!\n");
    return 2;
  }
  else if(id==0)  //child
  {
    close(_pipe[0]);
    int i=0;
    char* _mesg_c=NULL;
    while(i<20)
    {
      if(i<10)
      {
        _mesg_c="i am a child!";
        write(_pipe[1],_mesg_c,strlen(_mesg_c)+1);
      }
      sleep(1);
      i++;
    }
  }
  else  //father
  {
    close(_pipe[1]);
    char _mesg[100];
    int j=0;
    while(j<3)
    {
      memset(_mesg,'\0',sizeof(_mesg));
      int ret=read(_pipe[0],_mesg,sizeof(_mesg));
      printf("%s:code is:%d\n",_mesg,ret);
      j++;
    }
    close(_pipe[0]);
    sleep(10);
    if(waitpid(id,NULL,0)<0)
    {
      return 3;
    }
  }
  return 0;
}
结果:
     i am a child!:code is:14
     i am a child!:code is:14
     i am a child!:code is:14
     
     Program exited normally.
     
4、如果有指向管道读端的文件描述符没关闭,而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么管道被写满时,再次write会阻塞,直到管道中有空位置了才写入数据并返回。
test4.c
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
  int _pipe[2];
  int ret=pipe(_pipe);
  if(ret==-1)
  {
    printf("create pipe error!error code is:%d\n",errno);
    return 1;
  }
  pid_t id=fork();
  if(id<0)   //create fail
  {
    printf("fork error!\n");
    return 2;
  }
  else if(id==0)  //child
  {
    close(_pipe[0]);
    int i=0;
    char* _mesg_c=NULL;
    while(i<20)
    {
        _mesg_c="i am a child!";
        write(_pipe[1],_mesg_c,strlen(_mesg_c)+1);
        sleep(1);
        i++;
    }
  }
  else  //father
  {
    close(_pipe[1]);
    char _mesg[100];
    int j=0;
    while(j<20)
   {
      if(j<3)
      {
        memset(_mesg,'\0',sizeof(_mesg));
        int ret=read(_pipe[0],_mesg,sizeof(_mesg));
        printf("%s:code is:%d\n",_mesg,ret);
      }
      sleep(1);
      j++;
   }
    if(waitpid(id,NULL,0)<0)
    {
      return 3;
    }
  }
  return 0;
}
结果:
     i am a child!:code is:14
     i am a child!:code is:14
     i am a child!:code is:14
     
     Program exited normally.


本文出自 “追寻内心的声音” 博客,请务必保留此出处http://ljy789.blog.51cto.com/10697684/1763811

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值