Android的进程通信及同步机制

一、 IPC经典实现

进程间通信(Inter-process communication, IPC)是指运行在不同进程(不论是否在同一台机器)中的若干线程间的数据交互。Android中有以下几种方式:

  1. 共享内存(Shared Memory)
    由于进程间可以通过直接共享访问同一块内存区域,减少了数据的复制操作,因而速度上的优势比较明显。
    实现步骤:创建内存共享区,并将共享区映射到需要共享的各进程空间里,之后便可访问并利用该区域进行信息交互,由于内存共享区没有同步机制,需要参与通信的诸进程自己协商处理。结束后需要撤销内存映射区并删除内存共享区。
  2. 管道(Pipe)
    通信双方分立管道两边,进行数据的传输通信
    管道同时具有“读取”端(read end)和“写入”端(write end).
    管道是单向的,如果一个进程既要“读”也要“写”,就需要建立两根管道。
    管道有容量限制。当Pipe满时写操作将阻塞;反之,读操作将阻塞。
  3. UNIX Domain Socket(UDS)
    UDS是专门针对单机内的进程间通信提出来的,有时也成为IPC Socket. Android中是有最多的一种IPC机制是Binder,其次就是UDS
    Network Socket是以TCP/IP协议栈为基础的,需要分包、重组等一系列操作。而UDS因为是本机内的“安全可靠操作”,实现机制上并不依赖这些协议。UDS的基本流程和Network Socket相似,通信流程图如下:
    UNIX Domain Socket的通信流程
  4. RPC(Remote Procedure Calls)
    RPC涉及的通信双方通常运行于两台不同的机器中。完整RPC通信过程如下:
    a. 客户端调用Stub接口;
    b. Stub根据操作系统的要求进行打包,并执行相应的系统调用;
    c. 服务器端Stub解包并调用与数据包匹配的进程;
    d. 进程执行操作;
    e. 服务器以上述步骤的逆向过程将结果返回给客户端。


    RPC通信图释
二、 同步机制的经典实现

这里所讲的同步,是指多个(包括两个)进程间存在时序关系,需要协同工作以完成一项任务。如果它们并不满足协同的条件,而只是因为共享具有排他性的资源时所产生的关系,则成为互斥。

  1. 信号量(Semaphore)
    信号量与PV原语时使用最为广泛的互斥方法之一,包括以下元素:
    a. Semaphore S(信号量), 用于指示共享资源的可用数量.
    b. Operation P (有时也称wait()), P操作可减少S的计数.
    c. Operation V (有时也称signal()), V操作可增加S的计数.


    PV操作图

当某个进程进入共享区时,先要执行P操作,想退出共享区时执行V操作. PV原语都属于原子操作,它们的执行过程不允许被中断.
Dijkstar创建的信号量机制只需要有限的几个元素和简单的操作就能解决同步问题,这也是它广泛流行的一大原因.

  1. Mutex(Mutual Exclusion)
    Mutex即互斥体,通常是对某一排他资源的共享控制 - 要么这个资被占用(unlocked),要么就是可以访问的(unlocked).
    只允许取0或1(即locked/unlocked)的Semaphore,叫做Binary Semaphore. 在很多操作系统中,Binary Semaphore和Mutex没有本质差异,前者是特定的Semaphore机制,而后者相较于Semaphore在实现上更为简单.
  2. 管程(Monitor)
    由于采用Semaphore机制的程序易读性差,对信号量的管理过于分散.为了使资源的互斥访问更利于维护,提出了"管程" : 可以被多个进程/线程安全访问的对象(object)或模块(module).
    它实际上是对Semaphore机制的延伸和改善,是一种控制更为简单的控制手段.
    管程中的方法都是受mutual exclusion保护的,意味着在同一时刻只允许有一个访问者使用它们.管程还具备如下属性: 安全性; 互斥性; 共享性.
    很多流行编程语言都实现了管程机制 : Java, Delphi, Python, Ruby C#等
  3. Linux Futex
    Futex(Fast Userspace muTEXes) 同步机制,优势就是快.
    在Linux2.6.x中称为内核主基线的一部分.Android中的ART虚拟机如果开启了ART_USE_FUTEXES宏,则ART虚拟机中的同步机制会以Futex为基石来实现.
    Mutex加锁的基本逻辑是:如果可以获取到锁,则直接返回;否则就进入挂起状态.在挂起等待后,如果用户态获取的状态已经发生了改变,则需要内核自行判断当前的最新状态. 对于不存在竞争的情况下,采用futex机制在用户态就可以完成锁的获取,而不需要通过系统调用进入内核态,从而提高了效率.
三、 Android中的同步机制

Android封装的同步类包括:

  1. Mutex - 进程间的同步
    Android中的Mutex只是对pthread提供的API的简单再封装.即可以处理进程内同步的情况,也可以解决进程间同步的问题.Mutex是用来保证共享资源的互斥使用的.
    Mutex只有0和1两种状态,提供了3个重要的接口函数:
status_t lock(); // 获取资源锁
status_t unlock(); // 释放资源锁
status_t tryLock(); // 不论成功与否都会及时返回,而不是等待.
  1. Condition - 条件判断
    核心思想是判断"条件是否已经满足" - 满足的话马上返回,继续执行未完成的动作;否则就进入休眠状态,知道条件满足时有人唤醒它.
    它是依赖Mutex来完成的. 和Mutex一样,它支持跨进程共享.主要接口:
/**
* wait方法直接调用了pthread提供的API方法,pthread_cond_wait的
* 逻辑语义如下:
* a. 释放锁mutex
* b. 进入休眠操作
* c. 唤醒后再获取锁
*/
inline status_t Condition::wait(Mutex& mutex) {
  return -pthread_cond_wait(&mCond, &mutex.mMutex);
}

/* 也是在某个条件下等待,增加了超时退出功能 */
status_t waitRelative(Mutex& mutex, nesec_t reltime); 

void signal(); // 条件满足时通知相应等待者

void broadcast(); // 条件满足时通知所有等待者
  1. Barrier - "栅栏,障碍"
    Barrier是对Condition的一个应用,是填充了"具体条件"的Condition. Barrier类是专门为SurfaceFlinger设计的,而Mutex和Condition是作为常用的Utility提供给整个Android系统使用的.
/* frameworks/native/services/surfaceflinger/Barrier.h */
class Barrier {
public:
  inline Barrier() : state(CLOSED) {}
  inline ~Barrier() {}

  void open() {
    Mutex::Autolock _l(lock);
    state = OPEND;
    cv.broadcast();
  }
  
  void close() {
    Mutex::Autolock _l(lock);
    state = CLOSED;
    cv.broadcast();
  }

void wait() const {
    Mutex::Autolock _l(lock);
    while( sate == CLOSED) {
      cv.wait(lock);
    }
  }

  private:
    enum {OPENED, CLOSED}
    mutable Mutex lock;
    mutable Condition cv;
    volatile int state;
}

以上满足的场景类似于,当汽车通过前,必须要先确认栅栏是开启的,于是调用wait().如果条件不满足只能停下来等待,直到管理员调用open()将栅栏打开.

  1. 加解锁的自动化操作 - Autolock
    在Mutex内部还有一个Autolock嵌套类,字面意思应该是为了实现加,解锁的自动化操作.
    当Autolock构造时,会主动调用内部成员变量mLock的lock()方法来获取一个锁. 而析构时的情况正好相反,调用它的unlock()方法释放锁. 这样假如一个Autolock对象是局部变量的话,那他的生命周期结束时就会自动把资源锁解除.

  2. 读写锁 - ReaderWriterMutex
    ReaderWriterMutex是Art虚拟机一种特殊的Mutex.
    Exclusive和Shared分别代表Write和Read权限,说明这个锁是允许多个对象共享Read锁,但同时只允许有唯一一个对象拥有Write锁.ReaderWriterMutex有三种状态:Free(还没被任何对象所持有的情况) /Exclusive/Shared.ReaderWriterMutex状态表如下:

State ExclusiveLock ExclusiveUnlock SharedLock SharedUnlock
Free Exclusive error SharedLock(1) error
Exclusive Block Free Block error
Free(n) Block error SharedLock(n+1) SharedLock(n-1)

注:主要内容摘录自书籍 深入理解Android内核设计思想,林学森 著

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容