Linux:进程间通信(匿名管道)

进程间通信

我们知道,进程之间是相互独立的,每个进程拥有自己虚拟地址空间,并且虚拟地址空间根据页表的映射,映射到属于自己的物理内存上。并且各个进程之间互相不影响,执行自己的代码。这样说来进程之间难道没有可能交流联系?显然是不可能的。
一般来说只要让我们互不相干的进程看到同一块公共资源,那么它们就可以在这片公共资源上面交流联系。与我们人一样,每个人都是一个独立的个体,但是到了一个公共场所,人与人之间就会不由的交流联系。

进程间通信的目的

进程之间的通信能够让进程之间进行数据的交换,并且这些进程共用一块公共资源,共同享有这些资源,进程之间进行信息的通知,如fork之后,子进程若退出则需要向父进程发送退出信息,让父进程来维护子进程的退出信息。同时,进程间如果能够通信交流,那么可以达到对进程的控制。

进程间通信的分类

进程间通信又分为管道通信、System V进程间通信、POSIX进程间通信。
而管道通信又分为匿名管道与命名管道通信。
System V进程间通信有:消息队列、共享内存、信号量,其中共享内存通信是速度最快的进程间通信方式。
POSIX进程间通信方式有:消息队列、共享内存、信号量、互斥量、条件变量、读写锁。


管道

说起管道通信,不由的就会想到在Linux平台下一个指令|这便是一个管道通信的方式。而管道是Unix中最古老的进程间通信方式,管道如同水管,一边进入一边流出。同理进程也是一样,数据从管道入口输入,再从出口输出。

匿名管道

我们的匿名管道是可以在代码中利用函数pipe(int fd[2])来创建的,如果管道创建成功返回0,失败返回错误码。

我们利用这个函数来实现一下我们的匿名管道通信。

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

int main()
{
  int pipefd[2];

  if(pipe(pipefd) != 0)
  {
    printf("pipe error!\n");
    return -1;
  }

  pid_t pid = fork();
  if(pid < 0)
  {
    printf("fork error!\n");
    return -1;
  }
  else if(pid == 0)
  {
    close(pipefd[0]);
    write(pipefd[1],"hello",5);
    close(pipefd[1]);
    exit(1);
  }
  else 
  {
    char buf[64];
    close(pipefd[1]);
    read(pipefd[0],buf,5);
    printf("%s\n",buf);
  }

  return 0;
}

这里利用fork产生一个子进程, 然后让子进程在之前创建的管道内进行写入内容,写入一个hello,然后父进程去读这个hello到buf里面。这里注意,由于管道是单向的,所以子进程在写入内容之前,需将管道的读入,也就是fd[0]关闭,在写完之后再将fd[1]关闭,防止外来因素影响,而父进程同理,在读之前将fd[1]关闭。
这里写图片描述

我们的管道在进行读写时,如果写满管道,write调用阻塞,那么这个时候管道将无法写入,直到有进程读走管道内数据。当没有数据可以读是,read调用阻塞,进程暂停,直到有数据写入。
当管道的所有写端对应的文件描述符被关闭的时候,那么read将返回0,如果管道的所有读端对应的文件描述符被关闭的时候,则write操作会产生SIGPIPE信号,导致write进程退出。

匿名管道特点

匿名管道只能用于具有血缘关系的进程之间进行通信,一般来说由一个进程先产生一个管道,接着调用fork生成子进程,父子进程共用管道,达到其通信的目的。而进程退出,匿名管道随之释放,也就是说匿名管道的生命周期随着进程。管道是单向的,数据只能从一个方向流往另一个方向,如果要双向通信,那么则需要再次创建新管道。我们前面说过,两个进程只有看到一片公共资源那么它们才能通信,此时的匿名管道便是这个公共资源,又叫做临界资源。


欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值