进程通信 订阅
进程通信是指在进程间传输数据(交换信息)。 [1]  进程通信根据交换信息量的多少和效率的高低,分为低级通信(只能传递状态和整数值)和高级通信(提高信号通信的效率,传递大量数据,减轻程序编制的复杂度)。其中高级进程通信分为三种方式:共享内存模式、消息传递模式、共享文件模式。 [1] 展开全文
进程通信是指在进程间传输数据(交换信息)。 [1]  进程通信根据交换信息量的多少和效率的高低,分为低级通信(只能传递状态和整数值)和高级通信(提高信号通信的效率,传递大量数据,减轻程序编制的复杂度)。其中高级进程通信分为三种方式:共享内存模式、消息传递模式、共享文件模式。 [1]
信息
分    类
操作系统
中文名
进程通信
进程通信原因
为了提高计算机系统的效率.增强计算机系统内各种硬件的并行操作能力.操作系统要求程序结构必须适应并发处理的需要.为此引入了进程的概念。进程是操作系统的核心,所有基于多道程序设计的操作系统都建立在进程的概念之上。目前的计算机系统均提供了多任务并行环境.无论是应用程序还是系统程序.都需要针对每一个任务创建相应的进程。进程是设计和分析操作系统的有力工具。然而不同的进程之间.即使是具有家族联系的父子进程.都具有各自不同的进程映像。由于不同的进程运行在各自不同的内存空间中.一方对于变量的修改另一方是无法感知的.因此.进程之间的信息传递不可能通过变量或其它数据结构直接进行,只能通过进程间通信来完成。并发进程之间的相互通信是实现多进程间协作和同步的常用工具.具有很强的实用性,进程通信是操作系统内核层极为重要的部分。
收起全文
精华内容
下载资源
问答
  • 进程通信
    千次阅读
    2021-08-25 21:02:39

    概述

    进程通信是指进程之间的信息交换。

    进程同步之中,也需要进程间交换一些信息,所以也可以归入进程通信中,但只能称为低级的进程通信。因为进程同步间的消息交换效率低、对用户不透明。
    在进程间要传送大量数据的时候,可以使用OS提供的高级通信工具,该工具的最主要特点是:使用方便、高效。

    进程通信的类型

    目前,高级通信机制可归结为四大类:共享存储器系统、管道通信系统、消息传递系统以及客户机-服务器系统。

    一、共享存储器系统

    在共享存储器系统中,相互通信的进程共享某些数据结构或共享存储区,进程间能够通过这些空间进行通信。因此也可以根据共享的内容划分成以下两种类型:

    1. 基于共享数据结构的通信方式:要求进程公用某些数据结构,借此实现进程间的信息交换,如生产者—消费者问题的有界缓冲区。操作系统仅提供共享存储器,由程序员负责对公用数据结构的设置及对进程间同步的处理。 这种通信方式仅适合传递相对较少的数据,通信效率低下,属于低级通信。
    2. 基于共享存储区的通信方式:为了加粗样式,在内存中划出了一块共享存储区域,各个进程可以通过对该共享区进行读写,实现通信,数据的形式和位置甚至访问控制都是由进程负责,而不是OS。当读写完成,不再需要的时候,将其归还给共享存储区。属于高级的通信方式。

    二、管道(pipe)通信系统

    管道:指用于连接一个读进程和一个写进程,以实现它们之间通信的一个共享文件,又名pipe文件。

    向管道(共享文件)提供输入的发送过程(写进程)以字符流形式将大量的数据送入管道;而接受管道输入的接受进程(读进程)则从管道中接受数据。由于发送进程和接收进程是利用管道进行通信,故又称管道通信

    为了协调双方的通信,管道机制必须提供以下三方面的协调能力:互斥、同步、确定对方是否存在(确定存在才能通信)

    三、消息传递系统

    该机制,进程不必借助任何共享存储区或数据结构,而是以格式化的消息为单位,将通信的数据封装在消息中,并利用操作系统提供的一组通信命令(原语),在进程间进行消息传递,完成进程间的数据交换。该方式属于高级通信方式。

    该方式隐藏了通信细节,使通信过程对用户透明化,降低通信程序的复杂性和错误率,称为当前应用最广泛的一类进程间的通信机制。例如:计算机网络中的格式化消息为报文

    其实现方式有两种:
    (1)直接通信方式:指发送进程利用OS所提供的发送原语,直接把消息发送给目的进程。

    1. 直接通信原语:
      1.1 对称寻址方式:要求发送进程和接收进程必须以显式方式提供对方的标识符。
      send(receiver,message); 发送一个消息给接收进程
      receive(sender,message); 接收Sender发来的消息
      1.2 非对称寻址方式:某些情况,接收进程可能需要与多个发送进程通信,无法事先指定发送进程,因此这种方式接收进程原语不需要命名发送线程。
      send(P,message); 发送一个消息给进程P
      receive(id,message); 接收任何进程的消息
    2. 消息格式:定长、不定长
    3. 进程的同步方式:有三种,发送进程和接收进程都阻塞直到有消息;发送进程不阻塞,接收进程阻塞;发送进程和接收进程均不阻塞,仅当发生某事件使它无法继续运行时才阻塞等待。
    4. 通信链路:在发送进程和接收进程两者间建立一条通信链路。

    (2)间接通信方式:指发送和接收进程,都通过共享中间实体(邮箱)的方式进行消息的发送和接收,完成进程间的通信。

    • 信箱通信:通过某种中间实体来完成进程通信。在公用缓冲区上暂存发送进程发送的消息,接收进程可以从该中间实体取出消息,该中间实体称为邮箱。每个邮箱都有一个唯一标识符。消息在邮箱中可以安全的保存,只允许核准的目标用户随机读取
      邮箱的类型:
      ① 私用邮箱:用户进程自己创建,并作为进程的一部分,邮箱拥有者从邮箱中读取消息,其他用户只能发送消息到该邮箱,可采用单向链路的邮箱实现。
      ② 共享邮箱:由某进程创建,创建时指出共享进程的名字。邮箱拥有者和共享者都能够取走发送给自己的消息
      ③ 公用邮箱:由操作系统创建,并提供给系统中所有核准进程使用。可读可发送,应该采用双向通信链路的邮箱来实现。

    四、客户机-服务器系统

    该机制是网络环境的各种应用领域当前主流的通信实现机制,主要实现放肆有:套接字、远程过程调用和远程方法调用。

    套接字

    一个套接字就是一个通信标识类型的数据结构,包含了通信目的地址、通信使用的端口号、通信网络的传输层协议、进程所在的网络地址,以及针对客户或服务器程序提供的不同系统调用等,是进程通信和网络通信的基本构建。

    套接字是为客户/服务器模型设计的,通常包括两类:

    1. 基于文件型:通信进程都运行在同一台机器的环境中,一个套接字关联到一个特殊的本地文件,通信双方通过对这个特殊文件的读写实现通信,原理类似管道。
    2. 基于网络型:该类型通常采用的是非对称方式通信,即发送者需要提供接受者命名。通信双方的进程运行在不同主机的网络环境下。
      工作过程:一般地,发送进程(客户端)发出连接请求时,随机申请一个套接字,主机为之分配一个端口,与该套接字绑定,不再分配给其它进程。接收进程(服务端)拥有全局公认的套接字和指定的端口(如ftp服务器-21,http服务器80等),并通过监听端口等待客户请求。因此任何进程都可以向它发出连接请求和信息请求,以便进程之间通信连接的建立。
      接收进程一旦收到请求,就接收来自发送进程的连接,完成连接,即在主机间传输的数据可以准确地发送到通信进程,实现进程间的通信;当通信结束时,系统通过关闭接收进程的套接字撤销连接

    套接字的优势在于,不仅使用与一台计算机内部的进程通信,也适用于网络环境中不同计算机间的进程通信。并且每个套接字拥有唯一的套接字号,确保了通信双方之间逻辑链路的唯一性。

    远程过程调用和远程方法调用

    远程过程(函数)调用 RPC:是一个通信协议,用于通过网络连接的系统。该协议允许运行于一台主机(本地)系统上的进程,调用另一台主机(远程)系统上的进程(例如在公司,远程调用关闭家里的空调),而对程序员表现为常规的过程调用,无需额外地为此编程。如果涉及的软件采用面向对象编程,那么远程过程调用也可称作远程方法调用。

    负责处理远程过程调用的进程有两个,一个是本地客户进程,另一个是远程服务器进程,这两个进程通常也被称为网络守护进程,主要负责在网络间的消息传递,一般情况下,这两个进程都是处于阻塞状态,等待消息。

    为了实现RPC的透明性,即就像调用本地过程一样,RPC引入一个存根的概念:在本地客户端,每个能够独立运行的远程过程都拥有一个客户存根,本地进程调用远程过程实际是调用该过程关联的存根,即调用的时候将控制权转移给存根,让存根来执行。


    本文为《计算机操作系统》第四版 学习笔记+个人总结

    更多相关内容
  • 进程通信

    千次阅读 2021-04-01 20:22:12
    进程通信的类型 进程通信类型包括低级通信和高级通信类型。 进程通信指进程之间的信息交换,进程同步所交换的信息量少,称为低级通信。 如:信号量机制是有效的同步工具,但作为通信工具,不够理想。 缺点:(1)...

    进程通信的类型
    进程通信类型包括低级通信和高级通信类型。
    进程通信指进程之间的信息交换,进程同步所交换的信息量少,称为低级通信。
    如:信号量机制是有效的同步工具,但作为通信工具,不够理想。
    缺点:(1)只能传递状态和整数值(控制信息),传送信息量小。(2)进程同步的细节由程序员实现,编程复杂。
    高级进程通信是指用户可直接利用操作系统所提供的一组通信命令,高效传送大量数据的一种通信方式。
    优点:其隐藏了进程通信的实现细节,减少了编程的复杂性。
    高级通信机制可归结为三类:
    1.共享存储器系统
    (1)基于共享数据结构的通信方式
    基于共享数据结构的通信方式,是指多个进程共用某些数据结构,实现进程间的信息交换。如生产者消费者问题中的有界缓冲区,只适合传输少量数据。
    (2)基于共享存储区的通信方式
    基于共享存储区的通信方式,是指在存储器中划出一个共享存储区,多个进程可通过对共享存储区中数据的读写,来实现通信。如复制粘贴操作,可以传输大量数据。
    在UNIX中,通过不同的命令对共享存储区进行操作。
    (1)创建或打开共享存储区:依据用户给出的整数值key,创建新区或打开现有区,返回一个共享存储区ID。
    (2)连接共享存储区:连接共享存储区到本进程的地址空间,可以指定虚拟地址或由系统分配,返回共享存储区首地址。
    (3)拆除共享存储区连接:拆除共享存储区与本进程地址空间的连接。
    (4)共享存储区控制:对共享存储区进行控制。
    2.消息传递系统
    消息传递系统是应用最广泛的进程通信机制。程序员直接利用操作系统所提供的一组通信命令,以格式化的消息为单位,实现大量数据的传递,隐藏了进程通信的实现细节。
    因实现方式的不同分为:
    (1)直接通信方式
    发送进程利用操作系统所提供的发送命令,直接把消息发送给目标进程。通常,系统提供下面两条通信原语:
    send(receiver,message)发送一个消息给接收进程。
    receive(sender,message)接收sender发来的消息。
    (2)间接通信方式
    在间接通信方式中,需要创建信箱;通过信箱进行消息的发送和接收。
    信箱的创建和撤销
    进程可利用创建信箱原语来建立一个新信箱。创建者进程应给出信箱名字、信箱属性;
    信箱属性可分为以下三类:
    (1)私用信箱
    (2)公用信箱
    (3)共享信箱
    对于共享信箱,应给出共享者的名字。当进程不再需要读信箱时,可用信箱撤销原语撤销。
    消息的发送和接收
    send(mailbox,message)将一个消息发送到指定信箱
    receive(mailbox,message)从指定信箱中接收一个消息
    3.管道通信系统
    管道是指用于连接一个读进程和一个写进程,以实现进程通信的一个共享文件,又名pipe文件。
    向管道提供输入的发送进程,以字符流形式将大量的数据送入管道;而接受管道输出的接收过程,则从管道中接收数据。
    由于发送进程和接收进程是利用管道进行通信的,故又称为管道通信。
    UNIX管道
    (1)通过pipe系统调用创建无名管道,得到两个文件描述符,分别用于写和读。
    int pipe(int fildes[2]);
    (2) 可通过mknod系统调用建立命名管道,
    int mknod(const char *path, mode_ t mode, dev_ t dev)
    消息传递系统实现中的若干问题
    1.通信链路
    根据通信链路的连接方法,又可把通信链路分为两类:
    ①点-点连接通信链路,一条链路只连接两个结点(进程)
    ②多点连接链路,用一条链路连接多个(n>2)结点(进程)。
    根据通信方式的不同,则又可把链路分成两种:
    ①单向通信链路,只允许发送进程向接收进程发送消息
    ②双向链路,既允许由进程A向进程B发送消息,也允许进程B同时
    向进程A发送消息
    2.消息格式
    消息格式分成消息头和正文两部分。
    消息头包括消息在传输时所需要的控制信息,如源进程名、
    目标进程名、消息长度、消息类型、消息编号、发送日期时间等;
    正文是发送进程所发送的数据。
    消息采用定长消息格式、不定长消息格式两种方式。
    (1)采用比较短的定长消息格式,减少了对消息的处理和存储开销。
    可用于办公自动化系统中;但这对要发送较长消息的用户是不方便的。
    (2)不定长的消息格式,即进程所发送消息的长度是可变的。系统在
    处理和存储变长消息时,须付出更多的开销,但方便了用户。
    这两种消息格式各有其优缺点,在很多系统中同时都使用的。
    3.进程同步方式
    (1) 发送进程阻塞、接收进程阻塞。
    发送进程和接收进程之间无缓冲,且进程之间紧密同步时,两进程平时处于阻塞状态,直到有消息传递时。
    (2)发送进程不阻塞、接收进程阻塞。
    发送进程可以发送多个消息,接收进程平时阻塞,直到发送进
    程发来消息时被唤醒。
    如:打印进程平时处于阻塞状态,直到发送进程发来打印消息
    时被唤醒;处理完后,若无新请求,又阻塞。
    (3)发送进程和接收进程均不阻塞。
    这是常见的进程同步形式。发送进程和接收进程都忙于自己
    的事情,仅当发生某事件无法继续执行时才阻塞。
    如:多缓冲区的生产者消费者问题;只有缓冲区满时,生产
    者才阻塞:只有缓冲区空时,消费者才阻塞。
    消息缓冲队列通信机制
    1.消息缓冲队列通信机制中的数据结构
    (1) 消息缓冲区。在消息缓冲队列通信方式中,主要利用的数据结构是
    消息缓冲区。它可描述如下:
    type message buffer=record
    sender;发送者进程标识符
    size;消息长度
    text;消息正文
    next;指向下一个消息缓冲区的指针
    end
    (2) PCB中有关通信的数据项。
    PCB中应增加的数据项可描述如下:
    type processcontrol block=record

    mq;消息队列队首指针
    mutex;消息队列互斥信号量
    sm;消息队列资源信号量
    end
    2.发送原语
    (1) 发送进程先在自己的内存空间,设置一发送区a,把待发送的消息正文、发送进程标识符、消息长度等信息填入其中,然后调用发送原语,把消息发送给接收进程。
    (2)发送原语根据发送区a中所设置的消息长度a. size来申请一 缓冲区i,把发送区a中的信息复制到缓冲区i中。
    (3)先获得接收进程的内部标识符j,然后将i挂在j. mq上。
    在这里插入图片描述
    3.接收原语
    接收进程调用接收原语receive (b),从自己的消息队列mq
    中摘下第一个消息缓冲区i,并将其中的数据复制到以b为首址的
    指定消息接收区内。

    展开全文
  • 进程通信和线程详解

    千次阅读 2022-02-11 21:51:05
    2.6 进程通信 进程通信:指进程之间的信息交换 低级通信:进程间仅交换一些状态和少量数据。如:进程之间的互斥与同步

    2.6 进程通信

    • 进程通信:指进程之间的信息交换
    • 低级通信:进程间仅交换一些状态和少量数据。如:进程之间的互斥与同步

    信号量机制作为通信工具的缺点:

    • 1、效率低
    • 2、通信对用户不透明

    高级通信:进程间可交换大量数据

    • 用户可直接利用操作系统提供的一组通信命令,高效地传送大量数据的一组通信方式。
    • 操作系统隐藏了进程通信的细节,对用户透明,减少了通信程序编制上的复杂性。

    进程通信(高级通信)

    • 一、进程通信的类型
    • 二、消息传递通信的实现方法
    • 三、消息传递系统实现中的若干问题
    • 四、消息缓冲队列通信机制

    一、进程通信的类型

    高级通信机制可归结为三大类:

    • 共享存储器系统
    • 消息传递系统
    • 管道通信系统

    1、共享存储器系统

    相互通信的进程间共享某些数据结构或共享存储区,通过这些空间进行通信。

    • 基于共享数据结构的通信方式(低级通信)
      进程公用某些数据结构,借以实现诸进程间的信息交换
      实现:
      公用数据结构的设置及对进程间同步的处理,都是程序员的职责。
      操作系统–提供共享存储器
      特点:低效。只适合传递相对少量的数据。

    • 基于共享存储区的通信方式
      在存储区中划出一块共享存储区,诸进程可通过对共享存储区中数据的读或者写来实现通信。

    2、消息传递系统

    • 进程间的数据交换,以格式化的消息为单位。
    • 程序员直接利用系统提供的一组通信命令(原语)进行通信。
    • 例:计算机网络:网络报文

    3、管道通信

    图片1

    二、消息传递通信的实现方法

    图片2

    1、利用直接通信原语解决生产者-消费者问题

    当生产者生产处一个商品(消息)后,便用send原语将消息发送给消费者进程;而消费者进程则利用receive原语来得到一个消息。若消息尚未产生出来,消费者必须等待,直至生产者进程将消息发送过来。
    图片3

    2、间接通信------通过信箱通信

    • 信箱用来暂存发送进程发送给目标进程的消息,接收进程则从信箱中取出发送给自己的消息。
    • 消息在信箱中可安全保存,只允许核准的目标用户随时读取
    • 利用信箱方式,既可实时通信,又可非实时通信。
    • 信箱可由操作系统创建,也可由用户进程创建,创建者是信箱的拥有者。

    信箱分类:

      私用信箱  用户进程自己创建  单向
      公用信箱  操作系统创建  双向
      共享信箱  某个进程创建
    

    公用信箱与共享信箱的区别:创建者不同。

    三、消息传递系统实现中的若干问题

    1、通信链路

    分类:

    (1)根据通信链路的建立方式:

    • 显式连接:先用“建立连接”命令(原语)建立一条通信链路;进行通信;然后用显式方式拆除链路。用于计算机网络。
    • 隐式连接:发送进程无须明确提出建立链路的要求,直接利用系统提供的发送命令(原语),系统会自动地为之建立一条链路。用于单机系统。

    图片4

    2、消息的格式

    • 单机系统环境:环境相同,消息格式简单
    • 计算机网络环境:环境不同,消息的传输距离很远消息格式也比较复杂。

    图片5

    3、进程同步方式

    在进程之间进行通信时,辅以进程同步机制,使诸进程间能协调通信。

    发送进程或接收进程在完成消息的发送或接收后,都存在两种可能性:进程或者继续发送(接收)或者阻塞。

       发送进程阻塞、接收进程阻塞   (紧密同步 没有缓冲区,发送进程发送的数据由接收进程直接接收)
       发送进程不阻塞、接收进程阻塞  (发送速度<接收速度)
       发送进程和接收进程均不阻塞     (发送速度和接收速度差不多,基本同步)
    

    四、消息缓冲队列通信机制

    原理:

    图片6

    (2)PCB中有关通信的数据项

    图片7

    2、发送原语

    图片8

    图片9

    图片10

    3、接收原语

    图片11

    2.7 线程的基本概念

    线程的引入

    1、进程的两个基本属性

    (1)进程是一个可以拥有资源的独立单位
    (2)进程是一个可以独立调度和分派的基本单位

    由此使进程成为了能独立运行的基本单位,构成了进程并发执行的基础。

    2、程序并发执行所需付出的时空开销

    • 进程拥有资源,使进程的创建、撤销和调度要付出较大的时空开销。
    • 这就限制了系统中所设置进程的数目,而且进程切换也不宜过于频繁,从而限制了并发程度的进一步提高。
    • 因此,将进程的两个属性由系统分开处理,其中第二个属性由线程来实现。

    3、线程——作为调度和分配的基本单位

    1. 轻型实体
    2. 独立调度和分派的基本单位
    3. 可并发执行
    4. 共享进程资源

    线程与进程的比较

    1. 调度的基本单位
      在引入线程的OS中,已把线程作为调度和分派的基本单位,因而线程是能独立运行的基本单位。当线程切换时,仅需保存和设置少量寄存器内容,切换代价远低于进程。在同一进程中,线程的切换不会引起进程的切换,但从一个进程中的线程切换到另一个进程中的线程时,必然会引起进程的切换。
    2. 并发性
      在引入线程的OS中,不仅进程之间可以并发执行,而且在一个进程中的多个线程之间也可以并发执行,甚至还允许在一个进程中的所有线程都能并发执行。同样,不同进程中的线程也能并发执行。
    3. 拥有资源
      进程可以拥有资源,并作为系统中拥有资源的一个基本单位。然而线程本身并不拥有系统资源,而是仅有一点必不可少的、能保证独立运行的资源。
    4. 独立性
      在同一进程中的不同线程之间的独立性要比不同进程之间的独立性低得多。因为要防止进程之间彼此干扰和破坏,每个进程都拥有一个独立的地址空间和其他资源,除了共享全局变量外,不允许其他进程的访问。但是同一进程中的不同线程往往是为了提高并发性以及进行相互之间的合作而创建的,它们共享进程的内存地址空间和资源,如每个线程都可以访问他们所属进程地址空间中的所有地址,如一个线程的堆栈可以被其他线程读写,甚至完全清除。由一个线程打开的文件可以供其他线程读、写。
    5. 系统开销
      线程创建和撤销所付出的开销要远低于进程,在线程切换时,其代价也远低于进程。
    6. 支持多处理机系统

    关于线程的基本状态,就绪、执行与阻塞与进程类似

    关于线程的控制块TCB,与PCB类似。

    • 线程标识符,为每个线程赋予一个唯一的线程标识符
    • 一组寄存器,包括程序寄存器PC,状态寄存器和通用寄存器的内容
    • 线程运行状态,用于描述线程正处于何种运行状态
    • 优先级,描述线程执行的优先程度
    • 线程专有存储区,用于线程切换时存放现场保护信息,和与该线程相关的统计信息等
    • 信号屏蔽,对某些信号加以屏蔽
    • 堆栈指针,在线程运行时,经常会进行过程调用

    线程控制块TCB,用于记录所有用于控制和管理线程的信息。

    多线程OS的进程有以下属性

    • 进程是一个可拥有资源的基本单位
    • 多个线程可并发执行
    • 进程已不是可执行的实体
    展开全文
  • Android跨进程通信Binder机制与AIDL实例

    千次阅读 2021-12-03 23:10:34
    文章目录进程通信1.1 进程空间划分1.2 跨进程通信IPC1.3 Linux跨进程通信1.4 Android进程通信Binder 跨进程通信2.1 Binder简介2.2 Binder驱动2.3 Binder原理AIDL编程Demo3.1 服务端3.2 客户端 在操作系统中,进程与...

    在操作系统中,进程与进程间的内存和数据都是不共享的。这样做的目的,是为了避免进程间相互操作数据的现象发生,从而引起各自的安全问题。为了实现进程隔离,采用了虚拟地址空间,两个进程各自的虚拟地址不同,从逻辑上来实现彼此间的隔离。两个进程之间要进行通信,就需要采用特殊的通信机制:进程间通信(IPC:Inter-Process Communication,即进程间通信或跨进程通信,简称 IPC)。

    进程通信

    1.1 进程空间划分

    一个进程空间分为 用户空间 & 内核空间(Kernel),即把进程内 用户 & 内核 隔离开来。二者的区别:

    1. 进程间用户空间的数据不可共享,所以用户空间 = 不可共享空间
    2. 进程间内核空间的数据可共享,所以内核空间 = 可共享空间,所有进程共用1个内核空间

    进程内 用户空间 & 内核空间 进行交互 需通过 系统调用,主要通过函数:

    1. copy_from_user():将用户空间的数据拷贝到内核空间
    2. copy_to_user():将内核空间的数据拷贝到用户空间

    在这里插入图片描述

    1.2 跨进程通信IPC

    • 进程隔离:为了保证 安全性 & 独立性,一个进程 不能直接操作或者访问另一个进程,即 Android 的进程是相互独立、隔离的
    • 跨进程通信(IPC:Inter-Process Communication):即进程间需进行数据交互、通信。

    跨进程通信的基本原理:
    在这里插入图片描述

    1.3 Linux跨进程通信

    我们知道,Android系统就是基于Linux内核实现的,咱们先简单了解一下Linux系统的IPC方式。虽然不同的资料对各种方式的名称和种类说法不完全相同,但是主要来说有如下6种方式:(1)管道 Pipe;(2)信号Signal;(3)信号量Semaphore;(4)消息队列Message Queue;(5)共享内存Shared Memmory;(6)套接字Socket。读者若想深入了解这些方式,可以自行查阅,这里不展开介绍,只需要知道有这六种方式即可。

    1.4 Android进程通信

    Android IPC的方式在不同的资料中有不同的说法,但从大方向上看,可以归纳为如下四种(这里仅对各种方式做简单介绍和优劣对比,对具体如何使用,不做讲解):

    1、Activity方式

    Activity是四大组件中使用最频繁的,咱们先从它说起。使用Activity方式实现,就是使用startActivity()来启动另外一个进程的Activity。我们在使用App的使用,往往会遇到如下几种情形:(1)浏览器中看到一篇比较不错的文章,分享到微信朋友圈或者微博;(2)在某个App中点击某个网址,然后界面跳转到浏览器中进行阅读;(3)使用美团外卖app,看到店家的电话,点击联系商家时,跳转到了电话拨打界面…这样的操作再频繁不过了。这些就是通过startActivity的方式从一个App,跳转到了另外一个App的Activity,从而实现了跨进程通信。

    我们知道,在调用startActivity(Intent intent)的时候,intent有两个类型:显式Intent和隐式Intent。显式Intent的使用方式如下,用于进程内组件间通信:

    Intent intent = new Intent(this,OtherActivity.class);
    startActivity(intent);
    

    隐式intent的使用方式如下,用于IPC:

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_CALL);
    startActivity(intent); //startActivityForResult()同样,这里不赘述
    

    Intent.ACTION_CALL就是字符串常量“android.intent.action.CALL”,这种方式通过setAction的方式来启动目标app的Activity,上述代码就是启动电话app的拨号界面,有时候还可以带上电话号码等参数。由上可知,Activity实现跨进程通信的方式,适合于不同App之间功能界面的跳转。

    2、Content provider(后面简称CP)方式

    当我们开发App需要用到联系人,多媒体信息等数据的时候,往往会通过系统提供Uri,采用CP的方式去获取。Android系统中,数据主要存储在自带的SqlLite数据库中。应用要共享SqlLite中的数据给其他App操作(增、删、改、查),就要用到CP,也就是说,CP主要用于跨进程数据库共享。Android系统提供了很多的CP来供其它App使用,如多媒体信息、联系人、日历等。如下图显示了Android系统提供的CP,包名都是以"com.android.providers“开头的:
    在这里插入图片描述
    这些用于共享的数据其实都是存储在系统数据库中的,如下显示了meida CP中的数据库:
    在这里插入图片描述

    App开发者也可以自定义CP,把自己的数据提供给其它app使用,也可以自己定义操作权限,如只允许其它app读取自己的数据,而不允许修改等。CP的使用场景,是提供数据共享。CP本质上还是在操作数据库,数据存储在sdcard中,所以建立连接和操作数据都是耗时操作,所以注意开辟子线程去操作。当数据库中数据有变化时,Content Observer监听到数据库变化也是有一定的滞后。

    3、Broadcase方式

    Broadcast使用非常简单,注册好广播,添加上action,就可以等着接收其他进程发出的广播。发送和接收广播时,还可以借助Intent来携带数据。但是广播的使用存在很多问题,被很多程序员吐槽,甚至鄙夷,所以选择用广播进行跨进程通信,是下下策。下面盘点一下Broadcast的槽点:

    1. Broadcast是一种单向的通信方式。当一个程序发送广播后,其他应用只能被动地接收,无法向发送者反馈。
    2. Broadcast非常消耗系统资源,会导致系统性能下降。
    3. 速度慢,容易造成系统ANR。且除了Parall Broadcast外,无法保证接收到的时间,甚至不一定能收得到。
    4. 如果使用Ordered Broadcast,一个Receiver执行时间过长,会影响后面接收者的接收时间,甚至还有可能被中间某个Receiver拦截,导致后面Receiver无法接收到。
    5. 发送者无法确定谁会接收该广播,而接收者也无发确认是谁发来的广播。
    6. 如果是静态注册的广播,一个没有开启的进程,都有可能被该广播激活。

    总而言之,言而总之,使用Broadcast来实现跨进程通信,是下下之策!

    4、Service方式

    启动Service的方式有多种,有的用于跨进程通信,有的用于进程内部模块之间的通信,下面仅简单介绍一下跨进程通信的方式。

    (1)startService()方式

    Intent startIntent = new Intent ();
    ComponentName componentName = new ComponentName(string packageName,string serviceClassName);
    startIntent.setComponent(componentName );
    startService( startIntent);
    

    该方式启动远程Service实现跨进程通信,耦合度比较低,功能及代码结构清晰,但是存在以下缺点:

    • 没有好的机制立即返回执行结果,往往Service完成任务后,还需要其他方式向Client端反馈。

    • Service端无法识别Client端是谁,只知道有启动命令,但无法知道是谁下的命令。

    • 在已经创建好Service情况下,每次调用startService,就会执行onStartCommand()生命周期方法,相比于bindService,效率低下。

    • 如果Client端忘记调用stopService()了,那么该Service会一直运行下去,这也是一个隐患。

      所以,针对上述缺点,往往建议startService()方式用于同一个App内,跨进程的方式用后面将要讲到的AIDL来实现。

    (2)bindService、Handler、Messager结合

    这种方式也可以实现跨进程通信,据说和AIDL具有相同的功效,但比AIDL使用简单,详细可以阅读博文【Android总结篇系列:Android Service】。

    (3)AIDL

    这种方式也是 bindService() 启动方式的一种使用情况,也是广受程序员们推崇的方式。前面说 startService() 和 Broadcast 如何不好,就是为了衬托 AIDL 如何的好!这是本文的主角,本文后面会专门详细讲解,这里不赘述。

    【总结】从如上的介绍来看,其实 Android 中跨进程通信的实现,就是利用四大组件来实现的。对方式的选择,我们总结一下:

    • 如果跨进程需要界面上的交互操作,用隐式startActivity()方式实现。
    • 如果需要共享数据,用Content Provider方式实现。
    • 排除前两种情形,就用AIDL。
    • 仅仅为了完成功能,又确实不会用AIDL的,就用Broadcast吧!!!虽然很low,但比实现不了功能还是强多了。

    Binder跨进程通信

    在这里插入图片描述

    传统的跨进程通信需拷贝数据2次,但 Binder 机制只需1次,主要是使用到了内存映射,具体下面会详细说明。

    跨进程通信的核心原理:内存映射,具体请看文章:操作系统:图文详解 内存映射

    对比 Linux (Android基于Linux)上的其他进程通信方式(管道、消息队列、共享内存、信号量、Socket),Binder 机制的优点有:

    在这里插入图片描述

    2.1 Binder简介

    Binder 跨进程通信机制 模型 基于 Client - Server 模式:
    在这里插入图片描述
    在这里插入图片描述

    此处重点讲解 Binder 驱动的作用和 原理:

    在这里插入图片描述

    2.2 Binder驱动

    在这里插入图片描述

    2.3 Binder原理

    在这里插入图片描述

    Client进程、Server进程 & Service Manager 进程之间的交互 都必须通过Binder驱动(使用 open 和 ioctl文件操作函数),而非直接交互。具体原因:

    • Client进程、Server进程 & Service Manager进程属于进程空间的用户空间,不可进行进程间交互;
    • Binder驱动 属于 进程空间的 内核空间,可进行进程间 & 进程内交互。

    所以,原理图可表示为以下(虚线表示并非直接交互—):

    在这里插入图片描述

    Binder驱动 & Service Manager进程 属于 Android基础架构(即系统已经实现好了);而Client 进程 和 Server 进程 属于Android应用层(需要开发者自己实现)。所以,在进行跨进程通信时,开发者只需自定义Client & Server 进程并显式使用上述3个步骤,最终借助 Android的基本架构功能就可完成进程间通信:
    在这里插入图片描述

    AIDL编程Demo

    前面我们讲到,为了克服 Linux 中 IPC 各种方式的缺点,在Android中引入了Binder机制。但是当说起Binder在Android中的使用时,几乎所有的资料都是在说 AIDL 的使用。AIDL 的全称是 Android Interface Definition Language,即Android接口定义语言,是 Binder 机制实现 Android IPC 时使用比较广泛的工具。

    本节将以一个 Demo 演示一下 AIDL 的基本实现步骤。源码地址:https://pan.baidu.com/s/1CyE_8-T9TDQLVQ1TDAEX2A 提取码:4auk 。如下两个图展示了该 Demo 的结构图和 AIDL 关键文件:

    在这里插入图片描述

    建立两个App,分别为Client端和Server端。

    ​ 这个比较 好理解,Server端就是包含了Service真正干活的那一端;Client端就是通过远程操控指挥的那一端,分别在不同的App中。如下图所示:

    在这里插入图片描述

    3.1 服务端

    1、在Server端main目录下建立aidl文件夹以及.aidl文件,并copy一份到Client端,如图6.1中②处所示结构。注意,Client端和Server端②处是一模一样的。另外,AS中提供了快捷方式创建aidl文件,在main处点击右键 > New > AIDL > AIDL File文件,按照提示给aidl文件命名即可自动创建完成,可以看到文件路径也是该项目的包名。

    在这里插入图片描述

    这里给aidl命名为IDemoService.aidl,这里需要注意的是命名规范,一般都是以“I”开头,表示是一个接口,其内容如下:

    //========== IDemoService.aidl========
    package com.songwei.aidldemoserver;
    // Declare any non-default types here with import statements
    interface IDemoService {
        void setName(String name);
        String getName();
    }
    

    2、Server端创建Service文件 AidlService.java,如图6.1中③处所示,代码如下:

    package com.songwei.aidldemoserver;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    
    public class AidlService extends Service {
        private final static String TAG = "aidlDemo";
    
        public AidlService() {
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.i(TAG, "server:[onCreate]");
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            Log.i(TAG, "server:[onBind]");
            return new MyBinder();
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            Log.i(TAG, "server:[onUnbind]");
            return super.onUnbind(intent);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.i(TAG, "server:[onDestroy]");
        }
    
        class MyBinder extends IDemoService.Stub {
            private String mName = "";
    
            public void setName(String name) throws RemoteException{
                Log.i(TAG, "server:[setName]");
                mName = name;
            }
    
            @Override
            public String getName() throws RemoteException {
                Log.i(TAG, "server:[getName]");
                return mName;
            }
        }
    }
    

    为了下文分析流程及生命周期,在其中各个方法中都添加了Log。同时,在Server端的AndroidManifest.xml文件中添加该Service的注册信息(注意exported属性值,如果有“intent-filter”,则默认值为true,否则为false。所以这里其实可以去掉,因为有“intent-filter”,其默认值就是true):

    <service
        android:name=".AidlService"
        android:exported="true">
        <intent-filter>
             <action android:name="com.songwei.aidl" />
        </intent-filter>
    </service>	
    

    3、编译Sever端和Client端App,生成IDemoService.java文件。

    ​ 当编译的时候,AS会自动为我们生成IDemoService.java文件,如图6.1和图6.2中④处所示。当你打开该文件的时候,是不是看到了如下场景?
    在这里插入图片描述

    惊不惊喜?意不意外?是不是一脸懵逼,大惊,卧槽,这尼玛啥玩意啊?

    AIDL 是 Android 接口定义语言,IDemoService.java 是一个java中的interface(接口),现在是不是若有所思了呢?AIDL 正是定义了 IDemoService.java 这个接口!!! 这个接口文件就是 AIDL 帮助咱们生成的 Binder 相关代码,这些代码就是用来帮助实现 Client 端和 Server 端通信的。前面第2步中提到的IDemoService.aidl文件,其作用就是作为原料通过AIDL来生成这些你貌似看不懂的代码的,第3步中的 AidlService.java 和后续在 Client 端App连接Server端App的时候,其实这个aidl文件就从来没有出现过,也就是说,它已经没有什么价值了。所以说,AIDL 的作用就是用来自动生成 Binder 相关接口代码的,而不需要开发者手动编写。有些教程中说,可以不使用AIDL而手动编写这份Binder代码,AIDL不是Binder实现通信所必需的,笔者也没有尝试过手动编写,如果读者您想挑战,可以尝试一下!

    咱们继续!打开IDemoService.java文件后,点击主菜单兰Code > Reformat Code (或 Ctrl + Alt +L快捷健),你会发现画面变成了下面这个样子:

    /*
     * This file is auto-generated.  DO NOT MODIFY.
     * Original file: D:\\ASWorkspace\\testDemo\\aidldemoclient\\src\\main\\aidl\\com\\songwei\\aidldemoserver\\IDemoService.aidl
     */
    package com.songwei.aidldemoserver;
    
    public interface IDemoService extends android.os.IInterface {
        /**
         * Local-side IPC implementation stub class.
         */
        public static abstract class Stub extends android.os.Binder implements com.songwei.aidldemoserver.IDemoService {
            private static final java.lang.String DESCRIPTOR = "com.songwei.aidldemoserver.IDemoService";
    
            /**
             * Construct the stub at attach it to the interface.
             */
            public Stub() {
                this.attachInterface(this, DESCRIPTOR);
            }
    
            /**
             * Cast an IBinder object into an com.songwei.aidldemoserver.IDemoService interface,
             * generating a proxy if needed.
             */
            public static com.songwei.aidldemoserver.IDemoService asInterface(android.os.IBinder obj) {
                if ((obj == null)) {
                    return null;
                }
                android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                if (((iin != null) && (iin instanceof com.songwei.aidldemoserver.IDemoService))) {
                    return ((com.songwei.aidldemoserver.IDemoService) iin);
                }
                return new com.songwei.aidldemoserver.IDemoService.Stub.Proxy(obj);
            }
    
            @Override
            public android.os.IBinder asBinder() {
                return this;
            }
    
            @Override
            public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
                switch (code) {
                    case INTERFACE_TRANSACTION: {
                        reply.writeString(DESCRIPTOR);
                        return true;
                    }
                    case TRANSACTION_setName: {
                        data.enforceInterface(DESCRIPTOR);
                        java.lang.String _arg0;
                        _arg0 = data.readString();
                        this.setName(_arg0);
                        reply.writeNoException();
                        return true;
                    }
                    case TRANSACTION_getName: {
                        data.enforceInterface(DESCRIPTOR);
                        java.lang.String _result = this.getName();
                        reply.writeNoException();
                        reply.writeString(_result);
                        return true;
                    }
                }
                return super.onTransact(code, data, reply, flags);
            }
    
            private static class Proxy implements com.songwei.aidldemoserver.IDemoService {
                private android.os.IBinder mRemote;
    
                Proxy(android.os.IBinder remote) {
                    mRemote = remote;
                }
    
                @Override
                public android.os.IBinder asBinder() {
                    return mRemote;
                }
    
                public java.lang.String getInterfaceDescriptor() {
                    return DESCRIPTOR;
                }
    
                @Override
                public void setName(java.lang.String name) throws android.os.RemoteException {
                    android.os.Parcel _data = android.os.Parcel.obtain();
                    android.os.Parcel _reply = android.os.Parcel.obtain();
                    try {
                        _data.writeInterfaceToken(DESCRIPTOR);
                        _data.writeString(name);
                        mRemote.transact(Stub.TRANSACTION_setName, _data, _reply, 0);
                        _reply.readException();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                }
    
                @Override
                public java.lang.String getName() throws android.os.RemoteException {
                    android.os.Parcel _data = android.os.Parcel.obtain();
                    android.os.Parcel _reply = android.os.Parcel.obtain();
                    java.lang.String _result;
                    try {
                        _data.writeInterfaceToken(DESCRIPTOR);
                        mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
                        _reply.readException();
                        _result = _reply.readString();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                    return _result;
                }
            }
    
            static final int TRANSACTION_setName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
            static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        }
    
        public void setName(java.lang.String name) throws android.os.RemoteException;
    
        public java.lang.String getName() throws android.os.RemoteException;
    
    }
    

    惊不惊喜?意不意外?这下是不是有种似曾相识的赶脚?这就是一个很普通的java中的接口文件而已,结构也非常简单。

    在这里插入图片描述

    神秘的面纱揭开一层了吧!后面在讲完Client端和Server端的连接及通信后,还会继续深入剖析这个文件。

    3.2 客户端

    Client端通过ClientActivity活动类来连接Server端AidlService并通信。ClientActivity.java 的内容如下,布局文件在此省略,比较简单,就两个按钮,一个用于绑定,一个用于解绑,看Button命名也很容易分辨:

    package com.songwei.aidldemoclient;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    import com.songwei.aidldemoserver.IDemoService;
    
    public class ClientActivity extends AppCompatActivity {
    
        private final static String TAG = "aidlDemo";
        private Button mBindBtn, mUnBindBtn;
        private IDemoService mDemoService;
        private boolean mIsBinded = false;
        private ServiceConnection mConn = new ServiceConnection() {
            //当与远程Service绑定后,会回调该方法。
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder binder) {
                Log.i(TAG, "client:[onServiceConnected]componentName=" + componentName);
                mIsBinded = true;
                //得到一个远程Service中的Binder代理,而不是该Binder实例
                mDemoService = IDemoService.Stub.asInterface(binder);
                try {
                    //远程控制设置name值
                    mDemoService.setName("Andy Song");
                    //远程获取设置的name值
                    String myName = mDemoService.getName();
                    Log.i(TAG, "client:[onServiceConnected]myName=" + myName);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            //该回调方法一般不会调用,如果在解绑的时候,发现该方法没有调用,不要惊慌,因为该方法的调用时机是Service被意外销毁时,比如内存不足时。
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i(TAG, "client:[onServiceDisconnected]");
                mIsBinded = false;
                mDemoService = null;
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mBindBtn = (Button) findViewById(R.id.btn_bind);
            mBindBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //Android5.0及以后,出于对安全的考虑,Android系统对隐式启动Service做了限制,需要带上包名或者类名,这一点需要注意。
                    Intent intent = new Intent();
                    intent.setAction("com.songwei.aidl");
                    intent.setPackage("com.songwei.aidldemoserver");
                    bindService(intent, mConn, BIND_AUTO_CREATE);
                }
            });
            mUnBindBtn = (Button) findViewById(R.id.btn_unbind);
            mUnBindBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //解除绑定,当调用unbindService时,一定要判断当前service是否是binded的,如果没有,就会报错。
                    if (mIsBinded) {
                        unbindService(mConn);
                        mDemoService = null;
                        mIsBinded = false;
                    }
                }
            });
        }
    }
    

    代码中对一些关键和容易忽略的地方做了注释,可以结合起来进行理解。

    End 运行

    ​ 运行的时候,需要先启动Service端进程,才能在Client端中点击“绑定”的时候绑定成功。完成一次“绑定”和“解绑”,得到的log如下所示:

    01-08 15:29:43.109 13532-13532/com.songwei.aidldemoserver I/aidlDemo: server:[onCreate]
    01-08 15:29:43.110 13532-13532/com.songwei.aidldemoserver I/aidlDemo: server:[onBind]
    01-08 15:29:43.113 13299-13299/com.songwei.aidldemoclient I/aidlDemo: client:[onServiceConnected]componentName=ComponentInfo{com.songwei.aidldemoserver/com.songwei.aidldemoserver.AidlService}
    01-08 15:29:43.114 13532-13547/com.songwei.aidldemoserver I/aidlDemo: server:[setName]
    01-08 15:29:43.114 13532-13546/com.songwei.aidldemoserver I/aidlDemo: server:[getName]
    01-08 15:29:43.114 13299-13299/com.songwei.aidldemoclient I/aidlDemo: client:[onServiceConnected]myName=Andy Song
    01-08 15:36:07.570 13299-13299/com.songwei.aidldemoclient I/aidlDemo: client:[onServiceDisconnected]
    

    可以结合前面的 ClientActivity.java 和 AidlService.java 代码中的添加的log,来理解一下这个流程。当然,最好是能够按照上面的步骤,亲自动手实现一遍,比看10遍更有效果。

    参考文章:

    1. Android性能篇之(七)Android跨进程通信篇
    2. Android跨进程通信:图文详解 Binder机制 原理
    展开全文
  • java进程通信方式

    千次阅读 2019-08-26 18:24:43
    由于内存管理的一些机制,导致两个进程间并不能直接的进行通信(在独立的用户空间),因此我们需要利用一些介质来完成两个进程之间的通信。以下是常用的进程通信方式。 管道(Pipe):管道是一种半双工的通信方式,...
  • ContentProvider跨进程通信

    千次阅读 2022-03-16 16:44:24
    A进程插入数据到数据库,步骤如下 1.创建数据库表: package com.example.demoa import android.content.Context import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper...
  • 易语言源码易语言进程通信模块源码.rar 易语言源码易语言进程通信模块源码.rar 易语言源码易语言进程通信模块源码.rar 易语言源码易语言进程通信模块源码.rar 易语言源码易语言进程通信模块源码.rar 易语言源码...
  • 操作系统实验一:父子进程通信

    千次阅读 2021-05-29 17:25:30
    操作系统实验一:进程的建立 一、 实验目的: ...设计思路:实验要求在 父子进程 之间实现进程通信,所以可以采用 fork() 函数来通过一个进程创建他的一个子进程。关于父子进程之间通信可以采用 无名
  • 5、了解什么是信号,利用信号量机制熟悉进程间软中断通信的基本原理, 6、熟悉消息传送的机理 ,共享存储机制 。 二、 实验环境 Ubuntu 20.10,gcc编译器 三、 实验内容 编写一段程序,使用系统调用fork( )创建两...
  • Android跨进程通信:图文详解 Binder机制 原理

    万次阅读 多人点赞 2017-06-22 10:31:24
    如果你接触过 跨进程通信 (IPC),那么你对Binder一定不陌生 虽然 网上有很多介绍 Binder的文章,可是存在一些问题:浅显的讨论Binder机制 或 一味讲解 Binder源码、逻辑不清楚,最终导致的是读者们还是无法形成一...
  • TCP与UDP协议初步学习——网络环境中分布式进程通信的基本概念 一、单机系统中进程通信方法 进程和进程通信是操作系统中最基本的概念,首先通过回忆操作系统课程中,关于单击系统中进程和进程通信的问题描述: 1)...
  • 进程通信方式

    千次阅读 2019-10-31 12:07:29
    进程通信方式1、管道2、消息队列3、共享内存4、信号量5.Socket 1、管道 通信方式是单向的 管道的通知机制类似于缓存,就像一个进程把数据放在某个缓存区域,然后等着另外一个进程去拿,并且是管道是单向传输的。 ...
  • 操作系统之三种进程通信方式

    千次阅读 2021-11-05 07:41:16
    1、共享存储: 通信进程共享一个存储空间,通过对该空间进行读/写操作进程通信 2、消息传递: 直接以格式化的数据“消息”为单位,通过“发送消息”&“接收消息”原语进行通信 消息传递有两种方式:1、直接通信...
  • 题目描述: 编写一主程序可以由用户选择如下三种进程通信方式: 使用管道来实现父子进程之间的进程通信 子进程向父进程发送自己的进程标识符,以及字符串“is sending a message to parent”。父进程则通过管道读出...
  • 操作系统实验——进程管理与进程通信

    千次阅读 多人点赞 2020-01-05 10:22:10
    实验一 进程管理与进程通信 一、实验目的 1、掌握进程的概念,明确进程的含义。 2、认识并了解进程并发执行的实质,进程的阻塞与唤醒,终止与退出的过程。 3、熟悉进程的睡眠、同步、撤消等进程控制方法。 4、分析...
  • 关于C语言中进程通信的5种方式

    千次阅读 2020-07-30 18:10:49
    Unix/Linux系统中C语言进程通信的5种方式进程通信广义进程通信方式单机环境中常见的进程通信方式管道通信命名管道内存映射信号共享内存 进程通信 操作系统中每个进程地址空间相互独立,进程间通信必须经过内核。 ...
  • 进程通信

    千次阅读 2018-08-18 18:53:54
    进程: 首先,先来讲一下fork之后,发生了什么事情...将子进程id返回给父进程的理由是:因为一个进程的子进程可以多于一个,没有一个函数使一个进程可以获得其所有子进程进程id。对子进程来说,之所以fork返回0...
  • 【计算机网络学习笔记11】进程通信与端口号、TCP、UDP、IPv6 一、 进程通信与端口号 从路由器来看,通信的两端是主机。实际上真正的通信是一台主机中的一个进程和另一台主机中的一个进程在交换数据。因此严格上讲,...
  • Linux——进程通信 一、实验目的 (1) 熟悉并掌握管道机制,并实现进程间通信 (2) 熟悉并掌握共享内存机制,并实现进程间通信 二、实验内容 任务一: (1)阅读以上父子进程利用管道进行通信的例子(例1),写...
  • 运行在不同主机上的进程通信

    千次阅读 2021-09-04 21:37:13
    而在计算机网络知识中比较关注的是运行在不同端系统之间的进程通信。在两个不同端系统上的进程,通过计算机网络交换报文而相互通信。发送进程生成并向网络中发送报文;接受进程接受这些报文并可能通过回送报文进行...
  • 文章目录零、前言一、实验内容二、实验步骤三、实验数据及源代码四、实验结果分析五、思考题1、进程创建与进程并发执行2、进程的睡眠、同步、撤消...信号机制实现软中断通信5、消息的发送与接收6、进程的共享存储区通信...
  • 不同主机间进程通信方式--socket

    千次阅读 2022-02-11 13:58:38
    Socket本身有“插座”的意思,在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。 既然是文件,那么理所当然的,我们可以使用文件描述符引用套接字。与管道类似的,Linux...
  • C++实现进程通信(管道pipe)

    千次阅读 2021-12-03 16:54:44
    管道不仅可以用于本机进程通信,还可实现跨网络进程通信,如同Socket通信,管道同样封装计算机底层网络实现,提供一个良好的API接口。 管道(Pipe)实际是用于进程通信的一段共享内存,创建管道的进程称为管道...
  • 操作系统之进程通信

    千次阅读 2020-02-09 13:20:34
    2.什么是进程通信 各进程的内存空间是相互独立的,一个进程不能访问另一个进程的内存空间。 但是进程间的相互通信是不可避免的 方案一 共享存储 为两个进程设立一个共享存储区,两个进程需要互斥(通过PV操作)的...
  • 操作系统进程通信实验

    千次阅读 2019-07-22 19:38:43
    通过 Linux 系统中管道通信机制,加深对于进程通信概念的理解,观察和体验 并发进程间的通信和协作的效果 ,练习利用无名管道进行进程通信的编程和调试 技术。 硬件环境 : window 软件环境: VWareUbuntu16.04 实验...
  • 广州大学2020操作系统实验一:进程管理与进程通信

    千次阅读 多人点赞 2020-07-24 17:15:57
    实验一 进程管理与进程通信 一、实验目的 1、掌握进程的概念,明确进程的含义。 2、认识并了解进程并发执行的实质,进程的阻塞与唤醒,终止与退出的过程。 3、熟悉进程的睡眠、同步、撤消等进程控制方法。 4、分析...
  • 进程通信概念和进程通信方式

    万次阅读 2017-05-08 19:11:01
    进程通信(IPC,Inter-Porcess Communcation)是进程进行通信和同步的机制。IPC提供两个基本操作: 发送(send message) 接收(receive message) 进程通信流程: 在通信进程之间建立通信链路 通过send/receive交换...
  • electron-vue 开发(二)——主进程和渲染进程通信 1.简介 electron是由Github开发,是一个用Html、css、JavaScript来构建桌面应用程序的开源库,可以打包为Mac、Windows、Linux系统下的应用。 electron是一个运行时...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 694,385
精华内容 277,754
关键字:

进程通信

友情链接: 源代码.zip