【進程間通信】無名管道實現進程間通信詳解

常見的進程間通信方式

傳統進程間通信方式

  • 無名管道(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跳轉;
  • 只存在於內存中,在文件系統不可見;
  • 遵循先進先出的規則。
發佈了34 篇原創文章 · 獲贊 41 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章