管道的用法

一、fork 的用法

fork 返回值 c++

在C++中,fork 是一个来自 Unix/Linux 系统的系统调用,用于创建一个与现有进程几乎完全相同的新进程。fork 的主要特点是它会返回两次,一次返回在父进程中,一次返回在子进程中。在父进程中,fork 返回新创建子进程的进程ID;而在子进程中,fork 返回0。如果fork失败,则在父进程中返回-1,并设置errno

以下是一个简单的C++示例,演示如何使用 fork

生成的结果如下:

二、什么是匿名管道 

匿名管道是linux中一种非常古老进程间通信方式,本质上就是一个内存级的文件。

一般用于父子进程间通信。概念上就是父进程与子进程共同使用一个管道文件来传输数据。

虽然父子进程都有对管道的读和写功能,但在使用时只能读或者写,因此管道是单向通信,半双工模式。

三.如何使用匿名管道

(一).pipe原理

参数是长度为2的整形数组,pipefd[0]代表读端文件描述符,pipefd[1]代表写端文件描述符。

返回值是int,创建成功返回0,失败返回-1,同时记录进errno。 

pipe的使用原理上,就是首先父进程创建一个管道文件,但同时赋予管道文件两个文件描述符。

一个是以读方式打开即pipefd[0],另一个是以写方式打开即pipefd[1]。

(二).pipe使用
以下面代码为例:

父进程使用write接口将字符串给管道,子进程从管道中接收字符串并打印。

同时,子进程的read系统接口会阻塞,直到父进程往管道中写完数据,read一次性将此时管道内数据读取完并清空管道。

当父进程关闭管道后,若管道中还有数据时read函数会一次性读取完并在下一次读取时返回0,没有数据时直接返回0。
 
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<unistd.h>
  4 #include<string>
  5 #include<assert.h>
  6 using namespace std;
  7 int main()
  8 {
  9   int pfd[2] = { 0 };
 10   int ret = pipe(pfd);
 11   assert(ret == 0);
 12   printf("main:%d\n",getpid());
 13   pid_t id = fork();
 14   assert(id >= 0);
 15  if (id < 0)
 16   {
 17         printf("Failed to fork\n");
 18         return -1;
 19   }
 20  else if(id == 0)
 21   {
 22          close(pfd[1]);
 23           //关闭写端
 24          char GetStr[1024] = { 0 };
 25           ssize_t i = read(pfd[0], GetStr, sizeof GetStr);//接收数据
 26          GetStr[i] = '\0';
 27          cout << GetStr << endl;
 28         printf("son:%d\n",getpid());
 29         //cout << getpid()<< endl;
 30          exit(0);
 31    }
 32   else
 33   {
 34         printf("parent:%d\n",getpid());
 35 
 36   }
 37      //父进程
 38   printf("main second:%d\n",getpid());
 39   close(pfd[0]);
 40   char str[1024] = "hello world";
 41   write(pfd[1], str, sizeof str);//发送数据
 42 
 43   return 0;
 44 }

输出结果如下:

四、命名管道 

1.什么是命名管道?

匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文件。

2.怎么创建命名管道(函数)?

命名管道可以从命令行上创建,命令行方法是使用下面这个命令:

mkfifo filename

命名管道也可以从程序里创建,相关函数有 :

#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char *filename,mode_t mode);

filename:命名管道的名字

mode:权限值

返回值:成功返回0,失败返回-1

3.命名管道的打开规则

如果当前打开操作是为读而打开FIFO时:

  • O_NONBLOCK (disable):阻塞直到有相应进程为写而打开该FIFO
  • O_NONBLOCK (enable):立刻返回成功

如果当前打开操作是为写而打开FIFO时 :

  • O_NONBLOCK (disable):阻塞直到有相应进程为读而打开该FIFO
  • O_NONBLOCK (enable):立刻返回失败,错误码为ENXIO

4.怎么使用命名管道?命名管道有什么用?(例子)

processA.cc
  1 #include "fifo.h"
  2 using namespace std;
  3 bool MakeFifo()
  4 {
  5     int n = mkfifo(FIFONAME, 0644);
  6     if(n < 0)
  7     {
  8         cout << "mkfifo fail" << endl;
  9         return false;
 10     }
 11     return true;
 12 }
 13 
 14 int main()
 15 {
 16     //创建命名管道
 17     if(!MakeFifo())
 18     {
 19         cerr << "mkfifo fail" << endl;
 20         return 1;
 21     }
 22     //打开fifo文件写
 23     int wfd = open(FIFONAME, O_WRONLY);
 24     if(wfd < 0)
 25     {
 26         cerr << "open fifo fail" << endl;
 27         return 2;
 28     }
 29     cout << "Process A is sending a message to process B" << endl;
 30     char message[] = "i am process A";
 31     write(wfd, message, sizeof(message));
 32 
 33     return 0;
 34 } 


  1 #include "fifo.h"
  2 using namespace std;
  3  
  4 int main()
  5 {
  6     //打开fifo文件写
  7     int rfd = open(FIFONAME, O_RDONLY);
  8     if(rfd < 0)
  9     {
 10         cerr << "open fifo fail" << endl;
 11         return 2;
 12     }
 13     cout << "receives messages from process A: ";
 14     char message[30];
 15     read(rfd, message, sizeof(message));
 16 
 17     cout << message << endl;
 18 
 19     return 0;
 20 }
 fifo.h

 1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <iostream>
  4 #include <cassert>
  5 #include <fcntl.h>
  6 #include <unistd.h>
  7 
  8 #define FIFONAME  "fifo"

五、匿名管道和命名管道的区别  

  • 匿名管道由pipe函数创建并打开。
  • 命名管道由mkfifo函数创建,打开用open
  • FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义

相关推荐

  1. nc

    2024-04-04 23:44:02       35 阅读
  2. QueryWrapper

    2024-04-04 23:44:02       15 阅读
  3. axios

    2024-04-04 23:44:02       11 阅读
  4. React <> </>

    2024-04-04 23:44:02       9 阅读
  5. pymysql基本

    2024-04-04 23:44:02       41 阅读
  6. css_auto

    2024-04-04 23:44:02       38 阅读
  7. 关于QUOTENAME

    2024-04-04 23:44:02       42 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-04 23:44:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-04 23:44:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-04 23:44:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-04 23:44:02       20 阅读

热门阅读

  1. 计算机组成原理讲解

    2024-04-04 23:44:02       20 阅读
  2. springboot和redis与jwt实现jwt的token双重拦截

    2024-04-04 23:44:02       20 阅读
  3. 爬虫开发教程及案例

    2024-04-04 23:44:02       19 阅读
  4. 领域驱动设计战术设计

    2024-04-04 23:44:02       20 阅读
  5. Docker运维

    2024-04-04 23:44:02       17 阅读
  6. 【Linux】GCC编译器(七)

    2024-04-04 23:44:02       15 阅读
  7. 蓝桥杯备考随手记: practise04

    2024-04-04 23:44:02       18 阅读
  8. 文心一言 vs GPT-4 -- 全面横向比较

    2024-04-04 23:44:02       15 阅读
  9. Universal_Robots_ROS2_Driver 安装问题详解(humble)

    2024-04-04 23:44:02       14 阅读
  10. webpack 热更新的实现原理

    2024-04-04 23:44:02       16 阅读