进程间通信之匿名管道和命名管道

目录

管道是什么

匿名管道

命名管道

命名管道创建方式

管道的特点:


管道是什么

概念管道是计算机通信领域设计者,设计出的一种单向通信的方式,linux原生提供管道通信

管道都是单向传输内容的
管道中传输的都是"资源"
管道通信不会将内容刷新到磁盘,是内存级的通信(效率高)

管道是半双工的:

全双工:既可以收又可以发,同时进行

半双工:要么在收要么发

匿名管道

//头文件
#include <unistd.h>

//函数
int pipe(int pipefd[2]);

//返回值
//成功返回0,失败返回-1,会设置错误码到errno中

//参数
//int pipefd[2]   
//输出型参数,我们提供一个数组传入,这个数组会被填充两个文件描述符,pipefd[0]是读,pipefd[1]是写

1、分别以读写方式打开同一个文件

2、fork()创建子进程

3、双方进程各自关闭自己不需要的文件描述符

4、进行通信

5、通信结束

#include<iostream>
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>
using namespace std;

int main()
{
    int pipefd[2];  //创建一个数组,接受文件描述符
    if(pipe(pipefd) < 0)    //判断管道是否创建成功
    {
        perror("pipe"); //失败打印pipe,然后退出
        return -1;
    }

    pid_t id = fork();  //创建一个进程
    if(id < 0)  //判读进程是否创建成功
    {
        perror("fork"); //失败打印fork,然后退出
        return -1;
    }

    if(id == 0) //我们让子进程进行读取
    {
        close(pipefd[1]);   //关闭写进程
        char buff[64];
        while(1)    //进行通信
        {
            ssize_t s = read(pipefd[0], buff, sizeof(buff));
            if(s > 0)
            {
                if(strcmp(buff, "q") == 0)
                {
                    cout << "quit" << endl;
                    break;
                }
                cout << "parent say: " << buff << endl;
            }
            else if(s == 0)
            {
                cout << "eof" << endl;
                break;
            }
            else
            {
                cout << "read error" << endl;
                break;
            }
        }
        close(pipefd[0]);   //关闭读进程
    }
    //父进程进程通信
    close(pipefd[0]);   //关闭读
    if(id > 0)
    {
        char buff[64];
        while(1)
        {
            cin >> buff;
            write(pipefd[1], buff, sizeof(buff));
            if(strcmp(buff, "q") == 0)
            {
                break;
            }
        }
    }

    //通信结束
    wait(NULL);
    close(pipefd[1]);   //关闭写
    return 0;
}

 

匿名管道的特点:

管道是用来进行具有血缘关系的进程进行进程间同通信 -- 常用于父子通信

a、写快,读慢,写满就不能写了

b、写慢,读快,管道没有数据的时候,读必须等待

c、写关,读0,表示读到了文件结尾

d、读关,写继续写,os终止写进程

命名管道

为了解决匿名管道只能父子间通信,产生了命名管道

命名管道创建方式

方式一:

mkfifo指令:

mkfifo 管道名        --创建一个命名管道

方式二:

mkfifo函数

//头文件
#include <sys/types.h>
#include <sys/stat.h>
//函数
int mkfifo(const char *pathname, mode_t mode);
//返回值    创建成功返回0,失败返回-1

//参数
//const char *pathname,创建的路径
//mode_t mode,创建权限

命名管道fifo是p标识管道文件

1、分别写一个客户端,一个服务端

2、服务端创建命名管道

3、服务端发送信息,客服端接受信息

4、通信结束,客服端和服务端退出

 服务端,server.cpp

#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
using namespace std;

int main()
{
    umask(0000);    //将权限掩码设置为0000
    if(mkfifo("./fifo", 0666))  //创建命名管道fifo
    {
        perror("mkfifo");
        return -1;
    }

    int fd = open("./fifo", O_WRONLY); //以写方式打开命名管道
    if(fd < 0)
    {
        perror("open");
        return -1;
    }

    char buff[64];
    while(1)
    {
        cin >> buff;
        write(fd, buff, sizeof(buff));
        if(strcmp(buff, "q") == 0)
        {
            cout << "quit" << endl;
            break;
        }
    }
    unlink("./fifo");   //删除命名管道
    return 0;
}

 客服端,client.cpp

#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
using namespace std;

int main()
{
    umask(0000);    //将权限掩码设置为0000
    if(mkfifo("./fifo", 0666))  //创建命名管道fifo
    {
        perror("mkfifo");
        return -1;
    }

    int fd = open("./fifo", O_WRONLY); //以写方式打开命名管道
    if(fd < 0)
    {
        perror("open");
        return -1;
    }

    char buff[64];
    while(1)
    {
        cin >> buff;
        write(fd, buff, sizeof(buff));
        if(strcmp(buff, "q") == 0)
        {
            cout << "quit" << endl;
            break;
        }
    }
    unlink("./fifo");   //删除命名管道
    return 0;
}

 

管道的特点:

1、匿名管道是用来进行具有血缘关系的进程进行进程间同通信 -- 常用于父子通信

2、管道具有通过让进程间协同,提供了访问控制 假如写满,需要等待被读取才能继续写入

3、管道提供的是面向流式的服务 -- 面向字节流 -- 协议

4、管道是基于文件的,文件的生命周期是随进程的,管道的生命周期是随子进程的

5、管道是单向通信的(半双工通信的一种特殊情况)

全双工:既可以收又可以发,同时进行

半双工:要么在收要么发

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
匿名管道命名管道都是用于进程间通信的方式,但它们之间有一些区别。 匿名管道匿名管道是一种单向通信方式,只能用于父子进程或者兄弟进程之间的通信。在创建匿名管道时,操作系统会自动为其分配一个文件描述符,通过该文件描述符,进程可以进行读写操作。 匿名管道的创建方式如下: ```C int pfd[2]; pipe(pfd); // 创建匿名管道 ``` 其中,pfd[0]是管道的读端,pfd[1]是管道的写端。 匿名管道的使用方式如下: ```C char buf[1024]; pid_t pid; int pfd[2]; pipe(pfd); pid = fork(); if (pid == 0) { // 子进程 close(pfd[1]); // 关闭写端 read(pfd[0], buf, sizeof(buf)); // 读取数据 printf("child process read from pipe: %s\n", buf); close(pfd[0]); // 关闭读端 } else if (pid > 0) { // 父进程 close(pfd[0]); // 关闭读端 write(pfd[1], "hello world", strlen("hello world")); // 写入数据 close(pfd[1]); // 关闭写端 } else { perror("fork"); exit(1); } ``` 命名管道命名管道也是一种单向通信方式,但可以用于任意进程之间的通信。在创建命名管道时,需要指定一个路径名,并且需要手动创建该文件。操作系统会为其分配一个文件描述符,通过该文件描述符,进程可以进行读写操作。 命名管道的创建方式如下: ```C int fd; mkfifo("/tmp/myfifo", 0666); // 创建命名管道 fd = open("/tmp/myfifo", O_RDONLY); // 打开命名管道 ``` 其中,"/tmp/myfifo"是文件路径名,0666是文件权限。 命名管道的使用方式如下: ```C char buf[1024]; int fd; fd = open("/tmp/myfifo", O_RDONLY); read(fd, buf, sizeof(buf)); // 读取数据 printf("read from fifo: %s\n", buf); close(fd); ``` 需要注意的是,命名管道的写入操作可以在任意进程中进行,只要有权限打开该文件即可。如果多个进程同时写入数据到同一个命名管道,可能会导致数据混乱。因此,使用命名管道时需要特别注意数据的同步问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一起慢慢变强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值