网络编程之 进程间的通信之管道的使用

简介: 如何使用管道是进程间通信的关键博主先声明一下,关于处理进程创建以及销毁的方法。 “子进程究竟何时终止????调用waitpid函数后还要无休止的等待子进程终止吗???”,这显然会是一个问题。因为父进程往往与子进程一样繁忙,因此我们不能只调用waitpid函数来等待子进程终止。那么我们应该怎么办呢???

如何使用管道是进程间通信的关键

博主先声明一下,关于处理进程创建以及销毁的方法。

   “子进程究竟何时终止????调用waitpid函数后还要无休止的等待子进程终止吗???”,这显然会是一个问题。因为父进程往往与子进程一样繁忙,因此我们不能只调用waitpid函数来等待子进程终止。那么我们应该怎么办呢???

     这就要涉及到我们后面要了解的内容了,信号的概念,我们可以制作信号捕捉器,来完美解决这个问题,由于信号的知识点较多也比较复杂所以博主将往后推移了。


                   那我们就开始吧!!

如何理解进程间通信

     进程 通信意味着两个不同进程间可以交换数据,为了完成这一点,操作系统中应提供两个进程可以同时访问的内存空间(我们也叫缓冲区。)

我们先看一下比较专业的解答吧。

     Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。

     其实就是进程一旦创建完成它就拥有完全独立的内存结构(0到4G的空间pcb控制块等等),就连通过 fork()创建的子进程也不会与父进程共享内存空间。因此我们就必须想想其他的办法完成进程间的通信了。只要有两个进程由可以同时访问的内存空间,那么进程间就可以通过此空间进行数据交换了。----------->这就是进程间通信。

那么如何实现我们上面所说的呢??这似乎也是一件麻烦事啊????

博主在这里唠叨一句下面的方法都能实现进程间通信,但是展开说实在太费篇幅,博主就简单提一提,如果有感兴趣的朋友可以去查一下相关的资料。


         在进程间完成数据传递需要借助操作系统提供特殊的方法,如:文件、管道、信号、共享内存、消息队列、套接字、命名管道等。随着计算机的蓬勃发展,一些方法由于自身设计缺陷被淘汰或者弃用。现今常用的进程间通信方式有:

① 管道 (使用最简单)

② 信号 (开销最小)

③ 共享映射区 (无血缘关系)

④ 本地套接字 (最稳定)


管道是什么?

管道是什么?

           既然我们要用到管道的话,那我们就先来聊一聊什么是管道吧。


IPC:下面给出百度百科的解释

20191028194044675.png

管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质:

1. 其本质是一个伪文件(实为内核缓冲区)

2. 由两个文件描述符引用,一个表示读端,一个表示写端。

3. 规定数据从管道的写端流入管道,从读端流出。

管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。

管道的局限性:

① 数据自己读不能自己写。

② 数据一旦被读走,便不在管道中存在,不可反复读取。

③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。(这就是半双工通信。)

④ 只能在有公共祖先的进程间使用管道。

(希望大家能记住上面的,还是比较重要的。)


给出管道的模型:

20191028194617321.png

通过上图我们可以看到,为了完成进程间通信(因为进程间的通信不能直接完成,所以我们不得不使用管道),我们需要创建管道。管道不属于进程的资源。而是和套接字一样,属于操作系统(也就不是fork()锁复制的对象)。所以,两个进程之间可以通过操作系统提供的内存空间进行通信。


下面给出创建管道的函数:

#include<unistd.h>
int pipe(int pipefd[2]);
  -->成功:返回 0
     失败:返回 -1

  函数调用成功返回read()/write()两个文件描述符。无需open(),但需手动close()。

         规定:fd[0] → read(); fd[1] → write(),就像0对应标准输入,1对应标准输出一样。向管道文件读写数据其实是在读写内核缓冲区


其实当你要使用管道时,博主在这里可以给你一些使用的小方法来帮助你去理解一些代码.

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#define BUF_SIZE 30
int main(void) {
  int fds[2];//因为你要调用 int pipe(int pipefd[2]) 这个函数所以你需要创建一个 int型的数组
  char str[] = "Who are you?";  //这个是你要写出去的字符串
  char buf[BUF_SIZE]; //用来接收的数组
  pid_t pid;//用来接收 fork()的返回值,来判断 父子进程
  pipe(fds);  //创建管道
  pid = fork(); //创建进程
  if (pid == 0) { //子进程
    write(fds[1], str, sizeof(str));  //将字符串 "Who are you?"写出去
  } else {  //父进程
    read(fds[0], buf, BUF_SIZE)); //将独到的字符串写到 buf数组里面 该数组大小为 BUF_SIZE
    puts(buf);  //输出
  }
  return 0;
}


2019102820241286.png


20191028202430365.png

大家对于管道的理解到这里就行了,鉴于书中还有单管道同时进行读写,这是不推荐使用的。


不推荐这种

20191028202535866.png

博主推荐的是下面这种方式使用管道

20191028202732316.png


为了完成这个模式我们需要使用以下代码:

20191028202812342.png

有了博主上面的讲解大奖看懂这个代码应该是很轻松地了。


目录
相关文章
|
4天前
|
负载均衡 网络协议 算法
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
这网络层就像搭积木一样,上层协议都是基于下层协议搭出来的。不管是ping(用了ICMP协议)还是tcp本质上都是基于网络层IP协议的数据包,而到了物理层,都是二进制01串,都走网卡发出去了。 如果网络环境没发生变化,目的地又一样,那按道理说他们走的网络路径应该是一样的,什么情况下会不同呢? 我们就从路由这个话题聊起吧。
22 4
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
|
26天前
|
安全 搜索推荐 网络安全
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
53 11
|
23天前
|
网络协议
计算机网络与通信
计算机网络基本概念:了解计算机网络的定义、功能、分类和拓扑结构(如总线型、星型、环型、树形、网状等)。 网络通信原理:了解网络通信的基本原理、协议和技术,如TCP/IP协议、网络通信设备等。
25 3
|
1月前
|
算法
数据结构之卫星通信网络(BFS)
本文介绍了卫星通信网络及其重要性,并探讨了广度优先搜索(BFS)算法在其中的应用。卫星通信网络通过在轨卫星提供全球覆盖的通信服务,尤其在偏远地区和紧急救援中发挥关键作用。BFS算法用于网络拓扑分析、路径规划和故障排除,确保通信网络的高效运行。文章还包括BFS算法的工作原理、特点、优缺点及其实现代码示例。
41 1
|
1月前
|
传感器 自动驾驶 物联网
探秘 5G 核心网络之 5G RAN:开启高速通信新时代
探秘 5G 核心网络之 5G RAN:开启高速通信新时代
63 4
|
1月前
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
1月前
|
消息中间件 存储 供应链
进程间通信方式-----消息队列通信
【10月更文挑战第29天】消息队列通信是一种强大而灵活的进程间通信机制,它通过异步通信、解耦和缓冲等特性,为分布式系统和多进程应用提供了高效的通信方式。在实际应用中,需要根据具体的需求和场景,合理地选择和使用消息队列,以充分发挥其优势,同时注意其可能带来的复杂性和性能开销等问题。
|
1月前
|
网络协议 算法 数据库
OSPF 与 BGP 的互操作性:构建复杂网络的通信桥梁
OSPF 与 BGP 的互操作性:构建复杂网络的通信桥梁
40 0
|
1月前
|
边缘计算 5G 数据处理
5G网络能耗管理:绿色通信的实践
【10月更文挑战第30天】
46 0
|
5月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解