[深入理解linux应用]-Linux进程间通信方式

系列 内容
深入理解linux应用 Linux进程间通信方式

环境:

平台 内核版本 安卓版本
RK3399 Linux4.4 Android7.1

文章目录

    • 1、Linux进程间通信方式
      • 1.1、管道(Pipe)和命名管道(FIFO)
      • 1.2、消息队列(Message Queue)
      • 1.3、共享内存(Shared Memory)
      • 1.4、套接字(Socket)

1、Linux进程间通信方式

1.1、管道(Pipe)和命名管道(FIFO)

Linux 进程间通信的方法中,管道和命名管道是最早的进程间通信方法之一,管道可以用于具有亲缘关系进程间的通信,命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,他还允许无亲缘关系进程间的通信。

  • 管道的特点
    管道是 Linux 支持的最初Unix IPC 形式之一,具有以下特点:
  1. 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
  2. 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
  3. 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存中。
  4. 数据的读写规则:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
  • 管道的局限性
    管道的主要局限性正体现在它的特点上:
  1. 只支持单向数据流;
  2. 只能用于具有亲缘关系的进程之间;
  3. 没有名字;
  4. 管道的缓冲区是有限的(管道存在于内存中,在管道创建时,最大只能为缓冲区分配一个页面大小的空间);
  5. 管道所传送的是无格式字节流,这就要求管道的读方和写方必须事先约定好数据的格式。
  • 命名管道
    管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在命名管道(named pipeFIFO)提出后,这个限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以 FIFO 的文件形式存在于文件系
    统中。这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信(能够访问该路径的进程以及 FIFO 的创建进程之间),因此,通过 FIFO,不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out)规则,对管道及 FIFO 的读总是从开始处返回数据,对它们的写则把数据添加到末尾。

FIFO 可以说是管道的推广,克服了管道没有名字的限制,使得无亲缘关系的进程同样可以采用先进先出的通信机制进行通信。 管道和 FIFO 的数据都是字节流,应用程序之间必须事先确定特定的传输"协议"(即通信双方约定好的数据格式)。所有使用管道的进程都必须在事先确保所使用的管道是存在的。

1.2、消息队列(Message Queue)

消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。消息队列是随内核持续的。

  • ** 消息队列的基本概念 **
  1. 消息队列是随内核持续的,只有在内核重起或者显式删除一个消息队列时,该消息队列才会真正被删除。
  2. 消息队列就是一个消息的链表。每个消息队列都有一个队列头,用结构struct msg_queue 来描述。队列头中包含了该消息队列的大量信息,包括消息队列的键值、用户 ID、用户组 ID 以及消息队列中消息数目等等,甚至记录了最近对消息队列读写进程的ID。用户可以访问这些信息,也可以设置其中的某些信息。
  3. 系统里记录消息队列的数据结构(struct ipc_ids msg_ids)位于内核中,系统中的所有消息队列都可以在结构 msg_ids 中找到访问入口。内核和消息队列就是通过这个全局的数据结构建立起联系的。
  • ** 消息队列的操作 **
    对消息队列的操作有三种类型:
  1. 打开或创建消息队列
    消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,只需提供该消息队列的键值(key)即可;

  2. 读写操作
    消息队列的读写操作非常简单。对于队列中的每个消息都有相同的数据结构,一般情况下,这个数据结构包含两部分内容:一个代表消息类型的成员(一个长整型的变量),从消息队列中读取消息的一个重要依据就是消息的类型,与此同时消息队列中消息的优先级也是通过消息的类型实现的;另一个成员就是消息的内容。因此,对于发送消息来说,首先预设一个与消息有相同结构的缓冲区并写入消息的类型和内容,调用相应的发送函数即可;对读取消息来说,首先分配一个与消息有相同结构的缓冲区,然后把消息读入该缓冲区即可。

  3. 获得或者设置消息队列属性
    消息队列的信息基本上都保存在消息队列头中,因此,可以分配一个类似于消息队列头的结构(struct msqid_ds),来返回消息队列的属性;同样可以设置该数据结构。

  • ** 消息队列的限制 **
    每个消息队列的容量(所能容纳的字节数)都有限制,该值因系统不同而不同。另一个限制是每个消息队列所能容纳的最大消息数。除了上述两个针对消息队列的限制外,系统对消息队列的限制还有系统范围内的最大消息队列个数,以及整个系统范围内的最大消息数。一般来说,实际开发过程中不会超过这些限制。

1.3、共享内存(Shared Memory)

  • ** System V 共享内存 **
    共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制。共享内存可以通过系统调用 mmap()映射普通文件(特殊情况下还可以采用匿名映射)机制实现,也可以通过 system V 的共享内存
    机制实现。进程间通信的共享内存方法,虽然应用接口和原理很简单,但是内部机制复杂。为了实现更安全通信,往往还与信号灯等同步机制共同使用。所以我们在这里只做一个简要的介绍。

  • ** 用系统调用 mmap()实现共享内存 **

1.4、套接字(Socket)

  • ** 概述 **

  • ** 使用套接字时几个重要的数据结构 **

  • ** 套接字编程中的几个重要的系统调用 **

你可能感兴趣的:([深入理解linux应用]-Linux进程间通信方式)