进程间通信之匿名管道pipe

IPC基本概念

进程间通信:InterProcess Communication

进程间通信常用的4种方式
a. 管道 - 简单
b. 信号 - 系统开销小
c. 共享映射区 - (有无血缘关系的进程间通信都可以)
d.本地套接字 - 稳定
e.消息队列

管道的概念

本质

1、内核缓冲区
2、伪文件 - 不占用磁盘空间

特点

1、读端,写端,对应两个文件描述符
数据写端流入, 读端流出
2、操作管道的进程被销毁之后,管道自动被释放
3、 管道默认是阻塞的

管道的原理

1、内部实现方式:队列
环形队列
特点:先进先出
2、缓冲区大小:
默认4k
大小会根据实际情况做适当调整

管道的局限性

1、队列
数据只能读取一次,不能重复读取

2、 匿名管道
适用于有血缘关系的进程

管道的读写行为

1、 读操作
有数据
read - 正常读,返回读出的字节数。

无数据
写端全部关闭
read解除阻塞,返回0
相当于读文件读到了尾部
没有全部关闭
read阻塞
2、写操作
读端全部关闭
管道破裂,进程被终止
内核给当前进程发信号SIGPIPE
读端没全部关闭
缓冲区写满了
write 阻塞
缓冲区没有满
write继续写

设置非阻塞

1、默认读写两端都阻塞
2、设置读端为非阻塞pipe(fd)
a、fcntl - 变参函数
修改文件属性 - open的时候对应flag属性
b、设置方法
获取原来的flags
int flags = fcntl(fd[0], F_GETFL);
设置新的flags
flag |= O_NONBLOCK;

创建匿名管道

int pipe(int fd[2]);
fd- 传出参数
fd[0] - 读端
fd[1] - 写端

父子进程使用管道通信

1、父进程读
– 关闭写端
2、子进程写
– 关闭读端

测试源码

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

int main(int argc, const char* argv[])
{
    int fd[2];
    int ret  = pipe(fd);
    if(ret == -1)
    {
        perror("pipe error");
        exit(1);
    }

    printf("fd[0] = %d\n", fd[0]);
    printf("fd[1] = %d\n", fd[1]);

    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork error");
        exit(1);
    }

    // 父进程 写 , 关闭读操作
    if(pid > 0)
    {
        sleep(1);
        close(fd[0]);
        char* p = "hello, world\n";
        write(fd[1], p, strlen(p)+1);
        close(fd[1]);

        wait(NULL);
    }
    else if(pid == 0)
    {
        close(fd[1]);
        char buf[1024];
        read(fd[0], buf, sizeof(buf));
        printf("buf = %s\n", buf);
        close(fd[0]);
    }

    return 0

测试结果

在这里插入图片描述

关键代码分析

1、 单个进程可以使用管道完成读写操作。
2、 父子进程间通信不需要sleep函数。
3、管道默认是阻塞的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值