Linux进程之管道通信

管道通信概述

管道,通常指指无名管道,是 UNIX 系统IPC最古老的形式。

  • 特点
    1.它是半双工的(即数据只能在一个方向上流动即数据读取出来了就没有了,具有固定的读端和写端。
    2.它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
    3.它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

无名管道函数

int pipe(int pipefd[2]);
函数说明:包含头文件 #include <unistd.h>
pipe用来创建管道,其中pipefd[0]为读取标识符,pipefd[1]为写入标识符
管道创建成功返回0,创建失败返回-1

DEMO

#include "stdio.h"
#include "unistd.h"
#include "string.h"
#include "stdlib.h"

int main()
{
        int fd[2];
        char buf[128]={0};
//            int pipe(int pipefd[2]);
        if(pipe(fd)==-1){
                printf("creat pipe failed\n");
        }
        int pid =fork();
        if(pid<0){
                printf("creat child failed\n");
        }else if(pid>0){
                sleep(3);
                printf("this is father\n");
                close(fd[0]);
                write(fd[1],"xiaoma",strlen("xiaoma"));
                wait();
        }else{
                printf("this is child\n");
                close(fd[1]);
                read(fd[0],buf,128);
                printf("buf=%s\n",buf);
                exit(0);
        }
}
执行结果
this is child  //这里会阻塞直到wirte
this is father
buf=xiaoma

有名管道函数

int mkfifo(const char * pathname, mode_t mode)
第一个参数为普通路劲,创建创建后FIFO的名字,第二个参数与open()函数mode参数一致,如果没有对应路径名字的文件,则可以用O_CREAT加上响应权限创建
创建成功返回0 否则返回-1 错误原因存在errno中
其中EEXIST 表示文件已经存在

DEMO

#include "stdio.h"
#include <errno.h>
#include "fcntl.h"


int main()
{
        char buf[30]={0};
        int nread;
        if((mkfifo("./file",0600)==-1)&&errno!=EEXIST){
                printf("mkfifo failed\n");
                perror("why");
        }
        int fd=open("./file",O_RDONLY);
        printf("open success\n");
        while(1){
                nread=read(fd,buf,30);
                printf("read %d byte form fifo,context:%s\n",nread,buf);

        }

        close(fd);
        return 0;

}
#include "stdio.h"
#include <errno.h>
#include "fcntl.h"
#include "string.h"
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
        int cnt=0;
        char *str = "message from fifo";
        int fd=open("./file",O_WRONLY);
        printf("write open success\n");
        while(1){
                write(fd,str,strlen(str));
                sleep(1);
                cnt++;
                if(cnt==5){
                        break;
                }
        }

        close(fd);
        return 0;

}

执行结果:
先执行读进程代码在执行写进程代码
在这里插入图片描述在这里等待写入数据
在这里插入图片描述
写入成功后
在这里插入图片描述

总结以及阻塞问题

我们在进程间需要通信时,首选了无名管道,那么就有他们的优点,当然,也有缺点存在,下面我们一起来总结一下管道的特点
1.管道是先进先出的方式。
2.管道是单双工通信。
3.管道可以用于有亲缘关系的进程之间的通信,也可以用于没有亲缘关系间的进程。
4.虽然FIFO文件的inode节点在磁盘上,但是仅是一个节点而已,文件的数据还是存在于内存缓冲页面中,和普通管道相同。
5.缺点:他只能单向传输数据。
6.管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小,管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式
7.我们在写代码时也发现了,在执行open,write,read等操作时会发生阻塞现象。
8.(补充)虽然会发生阻塞现象,但是是可以解决的,我们只需要在read函数中的宏设置为非阻塞方式即可。

读/写,阻塞/非阻塞
阻塞
默认不指定0_ NONBLOCK时即为阻塞模式
●open以只读方式打开FIFO时,要阻塞到某个进程为写而打开此FIFO
●open以只写方式打开FIFO时,要阻塞到某个进程为读而打开此FIFO

●open以只读+ 只写方式打开FIFO时,调用read函数时read会阻塞
●调用write函数向FIFO写数据时 ,当缓冲区已满时write会阻塞
●通信过程中若写进程先退出了,则调用read函数从FIFO里读数据时不阻塞;若写进程又重新运行,则调用read函数从FIFO里读数
据时又恢复阻塞
●通信过程中若读进程先退出,则写进程向FIFO写数据,会收到SIGPIPE信号而退出
●open以读写方式打开FIFO时, open不阻塞
非阻塞
●open以只读方式打开FIFO ,如果没有进程为写而打开FIFO,只读open成功,并且open不阻塞
●open以只写方式打开FIFO,如果没有进程为读而打开FIFO,只写open将出错返回-1 ( ENXIO: No Such device or address)
●read, write读写FIFO中数据时不阻塞
●通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程会收到SIGPIPE信号而退出
●无论是无名管道还是有命管道都是消息读走就没有了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值