无名管道(PIPE)和有名管道(FIFO)---@颜麓

无名管道(PIPE)和有名管道(FIFO)

1、无名管道(PIPE)

无名管道(匿名管道),是一种具有两个端点的通信通道,管道的一端用于读取管道内数据,另一端用于将数据写入到管道内。创建一个管道后,会获取一对文件描述符,用于读取和写入。匿名管道通常是用在父子进程之间,由父进程创建匿名管道,子进程会继承管道的读端和写端,实现通讯。

管道是单向的、先进先出的、无结构的字节流。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。

由于PIPE 存在于内存中,并且只有创建它的进程可以直接拿到读写两个文件描述符,其他的进程要想获取到这两个描述符相对来说比较困难,通常做法是父进程先创建无名管道,再创建子进程。由于子进程继承父进程打开的文件描述符,所以父子进程就可以通过无名管道进行通信。

无名管道是临时的,在通讯完成进程退出后,将自动消失,对管道的读写可以使用 read 和write函数。

无名管道默认情况下只有64KB

PIPE的创建
在这里插入图片描述
实例1

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(void)
{
        pid_t pid=fork();
        int fd[2];
        if(pipe(fd) == -1)
        {
                perror("pipe");
                exit(EXIT_FAILURE);
        }
        if(pid == 0)
        {
                char buff[64]={0};
                char* str="son:i get!";
                write(fd[1],str,strlen(str));
                read(fd[0],buff,sizeof(buff));
                printf("%s\n",buff);
        }
        if(pid > 0)
        {
                char buff[64]={0};
                char* str="dad:hi! my son!";
                write(fd[1],str,strlen(str));
                read(fd[0],buff,sizeof(buff));
                printf("%s\n",buff);
        }
        close(fd[0]);
        close(fd[1]);
        if(pid < 0)
        {
                perror("fork");
                close(fd[0]);
                close(fd[1]);
                exit(EXIT_FAILURE);
        }
        return 0;
}

在这里插入图片描述
实例2

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(void)
{
        pid_t pid=fork();
        int fd[2];
        if(pipe(fd) == -1) 
        {
                perror("pipe");
                exit(EXIT_FAILURE);
        }
        if(pid == 0)
        {
                int count=0;
                char *str="a";
                while(1)
                {
                        write(fd[1],str,strlen(str));
                        count++;
                        printf("%d\n",count);
                }
        }
        close(fd[0]);
        close(fd[1]);
        if(pid < 0)
        {
                perror("fork");
                close(fd[0]);
                close(fd[1]);
                exit(EXIT_FAILURE);
        }
        return 0;
}

运行结果:
在这里插入图片描述

一个char型字符一个字节,64kb刚好就是65536个字节

2、有名管道(FIFO)

(1)概念:
有名管道(命名管道),不同与无名管道的是有名管道可以用于不相关的进程之间进行通讯,

创建有名管道的进程可以给管道取名字以及路径,该路径名是以特殊的文件存在放在文件系统中,因此两个进程可以通过访问该路径来建立联系,进行进程间的数据交换,有名管道和无名管道都遵循先进先出的原则。

有名管道是一个特殊的文件,它和普通的文件一样具有磁盘存放路径,文件权限和其他属性,但是两者又有区别,有名管道并不会在磁盘中存放真正的信息,信息存放在内存中。通讯的两个进程结束后,信息会自动消失,但管道文件路径依然存在。

(2)特点
两个进程已经完成打开有名管道操作,中途其中一个进程退出:
a)如果退出的是读操作,则写操作将返回 SIGPIPE 信号;
b)如果退出的是写操作,则读操作将不再阻塞,直接返回0
在这里插入图片描述
实例3

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#define  FI_PATH  "/home/yanlu/info"//管道路径
int main()
{
        if(access(FI_PATH,F_OK) == -1) 
        {
                if(mkfifo(FI_PATH,0666) < 0)
                {
                        perror("mkfifo");
                        exit(EXIT_FAILURE);
                }
        }
        int fd=open(FI_PATH,O_WRONLY);
        if(fd == -1) 
        {
                perror("open");
                exit(EXIT_FAILURE);
        }
        char pp[64]={0};
        sprintf(pp,"%d",getpid());
        write(fd,pp,strlen(pp));
        close(fd);
    
        return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#define  FI_PATH  "/home/yanlu/info"
int main()
{
        if(access(FI_PATH,F_OK) == -1)
        {
                if(mkfifo(FI_PATH,0666) < 0)
                {
                        perror("mkfifo");
                        exit(EXIT_FAILURE);
                }
        }
        int fd=open(FI_PATH,O_RDONLY);
        if(fd == -1)
        {
                perror("open");
                exit(EXIT_FAILURE);
        }
        char pp[64]={0};
        read(fd,pp,sizeof(pp));
        printf("%d\n",getpid());
        close(fd);

        return 0;
}

使用有名管道info将写进程的pid通过读进程读取
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值