IPC机制(一)---基础知识

目录

1.每日一句

2. 作者简介

3、Android IPC简介

        3.1 IPC全称Inter-Process Communication

        3.2 Android独特的IPC机制

4.Android中的多进程

        4.1 开启多进程

        4.2 多进程运行模式机制

 5.IPC基础概念介绍

        5.1 Serializable接口

        5.2 Parcelable接口

        5.4 Serializable 与 Parcelable对比


1.每日一句

岂能尽如人意,但求无愧于己

2. 作者简介

🏡个人主页:XiaoChen_Android

📚学习专栏:Android

🕒发布日期:2022/9/18

本文是基于Android开发艺术探索中IPC机制所写,就当做做笔记啦

3、Android IPC简介

        3.1 IPC全称Inter-Process Communication

        含义为进程间通信或跨进程通信,是指在两个进程之间进行数据交换。那么什么是进程呢?它与我们常说的线程之间的关系又是什么?

        按照操作系统的描述,线程是CPU调度的最小单元,而进程一般是指一个执行单元,在Android中进程一般是指一个应用程序,一个进程可以包含一个或多个线程。每个Android应用都有一个主线程,也就是我们常说的UI线程,假如我们试图在非主线程上更新UI,系统会抛出CalledFromWrongThreadException异常。

        很多时候,一个进程中需要执行大量的耗时任务,如果这些任务都放在主线程中去执行,就会造成界面无法响应,严重影响用户的体验,这种情况在PC系统和移动系统都存在,在Android中有一个特殊的名字叫ANR(Application Not Responding),即无响应。解决这个问题就需要用到线程,把一些耗时任务放在线程中。 

        3.2 Android独特的IPC机制

        IPC不是Android独有的,任何一个操作系统都有相应的IPC机制,比如Windows上可以通过剪贴板、管道和邮槽等来进行进程间通信;Linux上可以通过命名管道、共享内存、信号量等来进行进程间通信。

        对于Android来说,它是一种基于Linux内核的移动操作系统,它的进程间通信方式并不能完全继承自Linux,相反,他有自己的进程间通信方式,其中最独特的就莫过于Binder了,通过它可以轻松地实现进程间通信。 

         使用多进程的情况一般都是这两种:

  1. 第一种情况就是一个应用因为某些原因自身需要采取多进程模式来实现,至于原因可能就比较多了,比如有些模块由于特殊原因需要运行在单独的进程中,又或者为了一个加大一个应用可使用的内存,所以需要通过多进程来获取多份内存空间
  2. 第二种情况就是当前应用需要向其他应用获取数据,由于是两个应用,所以必须采用跨进程的方式来获取所需的数据,甚至我们通过ContentProvider去查询数据的时候其实也是一种进程间通信,只不过通信细节被系统内部屏蔽了。

总之,如果采取了多进程的方式,就必须处理好进程间通信的各种问题

4.Android中的多进程

        4.1 开启多进程

正常情况下,在Android中多进程是指一个应用中存在多个进程的情况,因此这里不讨论两个应用之间的多进程情况。首先在Android中使用多进程只有一种方法,那就是给四大组件在AndroidMenifest中指定android:process属性,除此之外没有别的办法,下面是一个示例:

<activity
            android:name=".SecondActivity"
            android:exported="false"
            android:process=":remote"/>

当SecondActivity启动时,系统会为它创建一个单独的进程,进程名称为"包名:remote"。其他没有指定android:process属性的Activity,会运行在默认进程中,默认进程名称与包名相同。我们可以在Android Studio中查看当前应用运行的进程列表。

属性android:process=":remote"中":"的含义是指要在当前进程名前面加上应用包名,这是一种简写的方法,对于SecondActivity来说,它的完整的进程名是com.example.ipc:remote。其次,进程名以":"开头的进程属于当前应用的私有进程,其他应用的组件不能和它运行在同一个进程中,不以这方式命名的进程属于全局进程,其他组件可以通过ShareUID与它运行在同一进程中。

         4.2 多进程运行模式机制

        Android系统为每个进程都分配一个独立的虚拟机,每个虚拟机在 内存分配上有不同的地址空间,这就导致在不同的虚拟机中访问同一个类的对象会产生多个副本。因此运行在不同进程的组件,是不能通过内存共享数据的,必须要借助一些中间层来实现数据共享。
一般来说,使用多进程会造成下面的几个问题:

  1. 静态成员和单例模式完全失效
  2. 线程同步机制完全失效
  3. SharedPreferences的可靠性下降
  4. Application会多次创建

第一个问题和第二个问题本质上是类似的,既然都不是一块内存了,那么不管是锁对象还是锁全局内都无法保证线程同步,因为对于不同进程,锁的不是一个同一个对象。第三个问题是因为SharedPreferences不支持两个进程同时去执行写操作,否则会有一定几率的数据丢失,这是因为SharedPreferences底层是通过读/写XML文件来实现的,并发写肯定是有可能出现问题的,甚至并发读/写都有可能出现问题。第四个问题,当一个组件跑在一个新的进程中时,由于系统在创建新的进程同时要分配独立的虚拟机,所以这个过程其实就是启动了一个应用的过程,很容易验证,只要在同一个Activity中运行三个不同的进程,看onCreate()方法是否被调用了三次即可

 5.IPC基础概念介绍

主要介绍Serializable接口、Parcelable接口以及Binder,只有熟悉这三方面的内容才能更好的理解跨进程通信的各种方式

        5.1 Serializable接口

Serializable时Java所提供的一个序列化接口,它是一个空接口,为对象提供标准的序列化和反序列化操作,使用Serializable来实现序列化很简单,只需要在类的声明中指定一个类似下面的标识即可自动实现默认的序列化过程

private static final serializableUID = 8711368828010083044L;

捷径: Android studio安装GenerateSerialVersionUID插件可以帮助开发者迅速生成SerialVersionUID

通过Serializable方式来实现对象的序列化,实现起来非常简单,几乎所有的工作系统自动完成了。如何进行对象的序列化和反序列化也非常简单,只需要采用ObjectOutputStream和ObjectInputStream即可,如下

//序列化过程
User user = new User(0 , "XiaoChen" , true);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
out.writeObject(user);
out.close;

//反序列化过程
ObjectInputStrea in = new ObjectInputStream(new FileOutputStream("cache.txt"));
User newUser = (User)in.readObject();
in.close();

只需要把实现了Serializable 接口的User对象写入到文件中,反序列化的时候就可以直接从文件中读取对象数据,恢复后的newUser对象与之前的对象虽然内容相同,但是并不是同一个对象。

         5.2 Parcelable接口

Parcelable也是一个接口。只要实现这个接口,一个类的对象就可以实现序列化并可以通过Intent和Binder传递,下面展示一个典型用法

package com.example.ipc;



import android.os.Parcel;
import android.os.Parcelable;

public class User implements Parcelable {
    public int userId;
    public String userName;
    public boolean isMale;
    
    public Book book;

    protected User(int userId , String userName , boolean isMale) {
        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int i) {
        out.writeInt(userId);
        out.writeString(userName);
        out.writeInt(isMale ? 1 : 0);
        out.writeParcelable(book, 0);
    }
    
    private User(Parcel in){
        userId = in.readInt();
        userName = in.readString();
        isMale = in.readInt() == 1;
        book = in.readParcelable(Thread.currentThread().getContextClassLoader());
    }
}

 先说一下Parcel,Parcel内部包装了可序列化的数据,可以在Binder中自由传输,从上述代码中可以看出,在序列化过程中需要实现的功能有序列化,反序列化和内容描述。序列化功能由writeToParcel方法来完成,最终是通过Parcel中的一系列write方法来完成的。反序列化由CREATOR来完成,其内部表明了如何创建序列化数组和对象,并通过Parcel的一系列read方法来完成反序列化过程;内容描述功能由describeContents方法来完成,几乎所有情况下这个方法都应该返回0,仅当当前对象中存在文件描述符时才返回1.

         5.3 Parcelable方法说明

        5.4 Serializable 与 Parcelable对比

  • Serializable 是Java中的序列化接口,使用起来简单;Parcelable是Android中的序列化方式,使用起来稍微复杂一些。
  • Serializable 在序列化操作的时候会产生大量的临时变量,从而导致GC的频繁调用(原因是使用了反射机制);Parcelable是以Ibinder作为信息载体的,在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable。
  • 将对象序列化到存储设备上或者序列化后通过网络传输,使用Parcelable 会稍显复杂,因此这两种情况建议使用Serializable。

由于Binder是很深的概念,这里不做过多介绍,下一篇将介绍Binder 

推荐阅读书籍:《Android开发艺术探索》

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: RT-Thread应用开发实战 PDF是一本关于RT-Thread嵌入式实时操作系统的实用指南。本书详细介绍了RT-Thread的基本概念和组成部分,介绍其多线程和实时性能优势,以及内核和驱动程序的开发方式。本书涵盖了多个应用场景,包括网络通信,文件系统,多媒体,以及图形用户界面等,并提供了具体实现案例和示例代码。本书的重点在于实践,通过实例演示,读者可以掌握如何构建实际应用和维护嵌入式系统的能力。 RT-Thread是一个开源的实时操作系统,可应用于嵌入式系统和物联网设备。由于其小型内核和高效的多线程机制,RT-Thread已成为一种广受欢迎的解决方案。本书的目的是帮助读者深入理解RT-Thread的工作原理和设计思路,学习如何构建高可靠性的嵌入式应用。 本书重点介绍了以下内容: 1. RT-Thread的开发环境和基本概念。 2. RT-Thread的内核和驱动程序开发方法。 3. RT-Thread的网络通信机制和应用案例。 4. RT-Thread的文件系统和多媒体支持。 5. RT-Thread的图形用户界面设计与实现。 6. RT-Thread的应用调试和性能优化技巧。 通过本书的阅读,读者可以深入了解RT-Thread的开发方法和使用技巧,从而更加有效地构建实际应用和维护嵌入式系统。 ### 回答2: 《RT-Thread 应用开发实战》是一本深入浅出介绍 RT-Thread 实现和应用开发的经典教材,共分为 10 章,作者采用了大量的实例代码和案例分析,帮助读者快速掌握 RT-Thread 的原理、使用方法和相关技巧。此书的阅读适合开发人员、嵌入式工程师、学生以及其他对嵌入式开发感兴趣的读者。 本书首先介绍了 RT-Thread 的基本概念和应用场景,包括嵌入式系统的软件架构、RTOS、多任务处理、任务、线程和 IPC基础知识。其次,本书详细讲述了 RT-Thread 的内核原理和驱动开发,包括线程、内存管理、中断处理、编译器、芯片、外设等相关知识。此外,本书还介绍了通过 CLI 库、AT 命令、LwM2M、MQTT、CMSIS-DAP 等外部库和协议实现应用开发的方法。最后,本书提供了一系列实用性极强的案例,包括 Ethernet、SD 卡、串口、I2C、SPI、USB 等常见应用的案例分享,帮助读者深入理解 RT-Thread 的应用场景和业务需求。 总的来说,本书通过清晰详细的讲解让读者掌握了 RT-Thread 的基础知识和应用开发技巧,并且提供了丰富的实例案例帮助读者在实际开发中遇到问题能够更好地解决。如果您正在进行嵌入式开发或对此感兴趣,那么这本书是绝对值得推荐的读物之一。 ### 回答3: 《RT-Thread应用开发实战》是一本针对嵌入式行业开发者编写的一本实用型技术书籍。该书对于初学者和专业人士来说都是一本非常重要的参考书。书中详细介绍了如何使用RT-Thread实现实时操作系统的开发和应用。 本书主要是从实战角度出发,以针对性和实用性为主,向读者展示了RT-Thread实践应用开发的方法。首先,本书从工具的安装、使用以及环境配置入手,让读者对RT-Thread有个初步的了解,方便读者上手实际开发。接着从任务、内存、文件系统、网络协议等方面介绍了RT-Thread的使用,详细讲解了每一部分的实现原理,并通过实例演示了每一部分的实际应用。 此外,本书还结合实际开发经验,分享了一些有用的技巧和经验。并提供了大量的代码示例、图表和实用工具,这些实用的资源能够有效地加快读者的开发进度,降低技术实现的难度。 总之,《RT-Thread应用开发实战》本是一本很实用的技术书籍,不仅可以帮助开发人员了解如何使用RT-Thread进行嵌入式应用开发,还可以帮助每一位读者深入理解实时操作系统和嵌入式系统的实现原理。无论是专业人士还是初学者,这本书都是值得推荐的好书。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值