相关的字符串定义在res/values/strings.xml文件中:
- xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="app_name">Ashmemstring>
- <string name="value">Valuestring>
- <string name="hint">Please input a value...string>
- <string name="read">Readstring>
- <string name="write">Writestring>
- <string name="clear">Clearstring>
- resources>
- xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="app_name">Ashmemstring>
- <string name="value">Valuestring>
- <string name="hint">Please input a value...string>
- <string name="read">Readstring>
- <string name="write">Writestring>
- <string name="clear">Clearstring>
- resources>
Ashmem
Value
Please input a value...
Read
Write
Clear
这样,界面的相关配置文件就介绍完了。
我们还要再来看程序描述文件AndroidManifest.xml的相关配置,它位于Ashmem目录下:
- xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="shy.luo.ashmem"
- android:sharedUserId="android.uid.system"
- android:versionCode="1"
- android:versionName="1.0">
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".Client"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- intent-filter>
- activity>
- <service
- android:enabled="true"
- android:name=".Server"
- android:process=".Server" >
- <intent-filter>
- <action android:name="shy.luo.ashmem.server"/>
- <category android:name="android.intent.category.DEFAULT"/>
- intent-filter>
- service>
- application>
- manifest>
- xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="shy.luo.ashmem"
- android:sharedUserId="android.uid.system"
- android:versionCode="1"
- android:versionName="1.0">
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".Client"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- intent-filter>
- activity>
- <service
- android:enabled="true"
- android:name=".Server"
- android:process=".Server" >
- <intent-filter>
- <action android:name="shy.luo.ashmem.server"/>
- <category android:name="android.intent.category.DEFAULT"/>
- intent-filter>
- service>
- application>
- manifest>
这里我们可以看到,下面的配置项把服务名称"shy.luo.ashmem.server"和本地服务类Server关联了起来:
- <service
- android:enabled="true"
- android:name=".Server"
- android:process=".Server" >
- <intent-filter>
- <action android:name="shy.luo.ashmem.server"/>
- <category android:name="android.intent.category.DEFAULT"/>
- intent-filter>
- service>
- <service
- android:enabled="true"
- android:name=".Server"
- android:process=".Server" >
- <intent-filter>
- <action android:name="shy.luo.ashmem.server"/>
- <category android:name="android.intent.category.DEFAULT"/>
- intent-filter>
- service>
这样,我们就可以通过startService(new Intent("shy.luo.ashmem.server"))来启动这个Server了。不过,在Android中,启动服务是需要权限的,所以,下面这一行配置获取了启动服务需要的相应权限:
- android:sharedUserId="android.uid.system"
- android:sharedUserId="android.uid.system"
android:sharedUserId="android.uid.system"
最后,我们来看工程的编译脚本文件Android.mk,它位于Ashmem目录下:
- LOCAL_PATH:= $(call my-dir)
- include $(CLEAR_VARS)
-
- LOCAL_MODULE_TAGS := optional
-
- LOCAL_SRC_FILES += $(call all-subdir-java-files)
-
- LOCAL_PACKAGE_NAME := Ashmem
-
- LOCAL_CERTIFICATE := platform
-
- include $(BUILD_PACKAGE)
- LOCAL_PATH:= $(call my-dir)
- include $(CLEAR_VARS)
-
- LOCAL_MODULE_TAGS := optional
-
- LOCAL_SRC_FILES += $(call all-subdir-java-files)
-
- LOCAL_PACKAGE_NAME := Ashmem
-
- LOCAL_CERTIFICATE := platform
-
- include $(BUILD_PACKAGE)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES += $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := Ashmem
LOCAL_CERTIFICATE := platform.
include $(BUILD_PACKAGE)
这里又有一个关键的地方:
- LOCAL_CERTIFICATE := platform
- LOCAL_CERTIFICATE := platform
LOCAL_CERTIFICATE := platform
因为我们需要在程序中启动Service,所以要配置这一行,并且要把源代码工程放在Android源代码平台中进行编译。
这样,整个例子的源代码实现就介绍完了,接下来就要编译了。有关如何单独编译Android源代码工程的模块,以及如何打包system.img,请参考如何单独编译Android源代码中的模块一文。
执行以下命令进行编译和打包:
- USER-NAME@MACHINE-NAME:~/Android$ mmm packages/experimental/Ashmem
- USER-NAME@MACHINE-NAME:~/Android$ make snod
- USER-NAME@MACHINE-NAME:~/Android$ mmm packages/experimental/Ashmem
- USER-NAME@MACHINE-NAME:~/Android$ make snod
USER-NAME@MACHINE-NAME:~/Android$ mmm packages/experimental/Ashmem
USER-NAME@MACHINE-NAME:~/Android$ make snod
这样,打包好的Android系统镜像文件system.img就包含我们前面创建的Ashmem应用程序了。
再接下来,就是运行模拟器来运行我们的例子了。关于如何在Android源代码工程中运行模拟器,请参考在Ubuntu上下载、编译和安装Android最新源代码一文。
执行以下命令启动模拟器:
- USER-NAME@MACHINE-NAME:~/Android$ emulator
- USER-NAME@MACHINE-NAME:~/Android$ emulator
USER-NAME@MACHINE-NAME:~/Android$ emulator
模拟器启动起,就可以在Home Screen上看到Ashmem应用程序图标了:

点击Ashmem图标,启动Ashmem应用程序,界面如下:

这样,我们就可以验证程序的功能了,看看是否实现了在两个进程中通过使用Android系统的匿名共享内存机制来共享内存数据的功能。
通过这个例子的学习,相信读者对Android系统匿名共享内存子系统Ashmem有了一个大概的认识,但是,这种认识还是停留在表面上。我们在文章开始时就提到,Android系统匿名共享内存子系统Ashmem两个特点,一是能够辅助内存管理系统来有效地管理不再使用的内存块,二是它通过Binder进程间通信机制来实现进程间的内存共享。第二个特点我们在上面这个例子中看到了,但是似乎还不够深入,我们知道,在Linux系统中,文件描述符其实就是一个整数,它是用来索引进程保存在内核空间的打开文件数据结构的,而且,这个文件描述符只是在进程内有效,也就是说,在不同的进程中,相同的文件描述符的值,代表的可能是不同的打开文件,既然是这样,把Server进程中的文件描述符传给Client进程,似乎就没有用了,但是不用担心,在传输过程中,Binder驱动程序会帮我们处理好一切,保证Client进程拿到的文件描述符是在本进程中有效的,并且它指向就是Server进程创建的匿名共享内存文件。至于第一个特点,我们也准备在后续学习Android系统匿名共享内存子系统Ashmem时,再详细介绍。
因此,为了深入了解Android系统匿名共享内存子系统Ashmem,在接下来的两篇文章中,围绕上面提到的两个特点,分别学习:
1. Android系统匿名共享内存子系统Ashmem是如何够辅助内存管理系统来有效地管理不再使用的内存块的?
2. Android系统匿名共享内存子系统Ashmem是如何通过Binder进程间通信机制来实现进程间的内存共享的?
学习完这两篇文章后,相信大家对 Android系统匿名共享内存子系统Ashmem就会有一个更深刻的认识了,敬请关注。
原博客链接:http://blog.csdn.net/luoshengyang/article/details/6651971

本文节选自《Android系统源代码情景分析》
电子工业出版社出版
罗升阳 著
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/13164110/viewspace-747976/
,如需转载,请注明出处,否则将追究法律责任。