【进程间通信】无名管道实现进程间通信详解

常见的进程间通信方式

传统进程间通信方式

  • 无名管道(pipe)
  • 有名管道(fifo)
  • 信号(signal)

System V IPC 对象

  • 共享内存(share memory)
  • 消息队列(message queue)
  • 信号灯(semaphore)

System V IPC 对象

  • 套接字(socket)
    在这里插入图片描述
    特点:
  • 只能用于具有血缘关系的进程间通信
  • 半双工的通信模式,有固定的读端和写端fd[0]为读端 fd[1]为写端,fd为整形数组最小有两个元素
  • 管道是一种特殊的文件,才在于内存中,在文件系统中不可见,可以用文件io函数来读写操作。如write(写)、read(读)。

无名管道的创建

在这里插入图片描述
父子进程间通信

/*************************************************************************
    > 功能:利用无名管道实现两个具有血缘关系的进程通信
 ************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
    pid_t pid;
    int fd[2];
    int rd;
    int wr;
    char buf[1024]={0};
//创建无名管道
    int ret=pipe(fd);
    if(ret<0)
    {
        perror("pipe error");
        exit(-1);
    }
//创建子进程
   pid= fork();
    if(pid<0)
    {
        perror("fork error");
        exit(-2);
    }
//子进程读 /关闭写端close fd[1]
    if(pid==0)
    {
        close (fd[1]);
        if((rd=read(fd[0],buf,sizeof(buf))) > 0)
        {
            printf("无名管道读到的东西是%s\n",buf);
        }
        close(fd[0]);
    exit(0);
    }
//父进程写 /关闭读端 close fd[0]
    if(pid>0)
    {
        memset(buf,0,sizeof(buf));
        gets(buf);
        close(fd[0]);
        if( (wr=write(fd[1],buf,sizeof(buf)))>0)
           {
               printf("这次写进去了%s\n",buf);
               waitpid(pid,NULL,0);
               exit(0);
           }
        close(fd[1]);
    }
    exit(0);
}

在这里插入图片描述
兄弟进程间通信

/*************************************************************************
	> File Name: pipe.c
	> Author: 
    > 功能:利用无名管道实现两个具有血缘关系的进程通信
	> Created Time: Tue 13 Aug 2019 08:12:22 PM PDT
 ************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<wait.h>
int main()
{
    pid_t pid;
    pid_t pid1;
    int fd[2];
    int rd;
    int wr;
    char buf[1024]={0};
//创建无名管道
    int ret=pipe(fd);
    if(ret<0)
    {
        perror("pipe error");
        exit(-1);
    }
//创建子进程
    pid= fork();
    pid1=fork();
    if(pid<0 || pid1<0)
    {
        perror("fork error");
        exit(-1);
    }
//子进程读 /关闭写端close fd[1]
    if(pid==0)
    {
        close (fd[1]);
        if((rd=read(fd[0],buf,sizeof(buf))) > 0)
        {
            printf("我是弟弟   ");
            printf("无名管道是%s\n",buf);
        }
        close(fd[0]);
    exit(10);
    }
//子进程1写 /关闭读端close fd[0]
    if(pid1==0)
    {
        memset(buf,0,sizeof(buf));
        gets(buf);
        close(fd[0]);
        if( (wr=write(fd[1],buf,sizeof(buf)))>0)
           {
            printf("我是哥哥\n");
           }
        close(fd[1]);
    exit(11);
    }
//父进程
    int status=0;
    int status1=0;
    if(pid>0)
    {
        sleep(1);
        wait(&status);
        printf("进程的退出状态是%d\n",WEXITSTATUS(status));
        wait(&status1);
        printf("进程1的退出状态是%d\n",WEXITSTATUS(status1));
    }
    exit(0);
}

在这里插入图片描述

无名管道使用需要注意的点

  • 无名管道只能用在具有亲缘关系的进程间通信
  • 是一种半双工的模式;意思是同一个时刻,只能读或者写;
  • 只有在管道读端存在时,写端才有意义;
  • 管道没有数据时,读端会一直阻塞;
  • 读完数据就立马消失;
  • 不能用fseek跳转;
  • 只存在于内存中,在文件系统不可见;
  • 遵循先进先出的规则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值