进程间通讯(IPC)——管道

操作系统对于不同的进程,彼此间是有隔离有保护的,使不同的进程不能够直接访问彼此的地址空间
管道是一种进程间通信的方式,分有名管道和无名管道,用于在进程间传递数据,但是属于半双工通讯(同一时刻,只能一端读,一端写)

有名管道:可以在任意进程间通讯

在磁盘上会存在一个管道文件标识,但管道文件并不会占用磁盘block空间,数据会缓存在内存上,有名管道可以应用于同一主机上有权限访问的任意n个进程间的通讯


无名管道:只能用于父子进程间通讯

不存在管道文件标识,是借助父子进程间共享fork之前打开的文件描述符,数据内容同样缓存在内存中,两个文件描述符分别以读写只想开辟的空间

 

 

有名管道使用:创建管道文件:命令:mkfifo  文件名   //   函数:int mkfifo(const char*pathname,int mode);

  1. 如果所有读端关闭,则写端也会退出,反之亦然,必须有至少一队读写
  2. 读写次数没有直接联系——字节流服务
  3. 如果写端保持,但没有写入数据,则读端阻塞,若读端保持,但没有获取数据,则写端在将管道内存写满时,阻塞
  4. 管道读端关闭,写端写入数据时,会引发异常,进而被信号SIGPIPE通知,若管道写端关闭,读端获取数据时,read返回0

 

无名管道使用:创建&打开:int pipe(fds[2]);   //创建无名管道并打开,使fds[0]为读端,fds[1]为写端

fork之后,父进程写(write(fds[1]);),子进程读(read(fds[0]);),反之也可。

父子进程必须关闭一对读写,且不能是同进程关(原因:1.逻辑上保持管道的半双工通讯 2.防止一端关闭读写,另一端无法感知)

 

有名管道相关代码:注:fifo是一个管道文件

写端如下

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

int main()
{
  int fd = open("fifo",O_WRONLY);
  assert(fd!=-1);


  while(1)
  {
    char buff[128]={0};
    printf("input:\n");
    fgets(buff,128,stdin);

    if(strncmp(buff,"end",3)==0)
    {
       break;
    }

    write(fd,buff,strlen(buff));
  }
  close(fd);
  exit(0);
}

读端如下

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

int main()
{
  int fd=open("fifo",O_RDONLY);
  assert(fd!=-1);

  while(1)
  {
    
    char buff[128]={0};
    int n=read(fd,buff,127);
    if(n<=0)
    {
        break;
    }
    printf("read:%s\n",buff);
  }
  close(fd);
  exit(0);
}

 

无名管道相关代码:

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

int main()
{
  int fd[2];
  int res=pipe(fd);
  assert(res!=-1);

  pid_t pid=fork();
  assert(pid!=-1);

  if(pid==0)
  {
    close(fd[1]);
    while(1)
    {
      char buff[128]={0};
      int n=read(fd[0],buff,127);
      if(n<=0)
      {
        break;
      }
      printf("child read:%s\n",buff);
    }
    close(fd[0]);
  }
  else
  {
    close(fd[0]);
    while(1)
    {
      char buff[128]={0};
      fgets(buff,128,stdin);
      if(strncmp(buff,"end",3)==0)
      {
        break;
      }
      write(fd[1],buff,strlen(buff));
    }
    close(fd[1]);
  }

  exit(0);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值