资源描述
Android的Linux内核和驱动程序
版本
时间
修订者
修订内容
1.0
2011-09-3
赵安璞
创建文档
文档修订记录
每次修改与增加内容者,需在文档修订记录中进行记录
1.1Android与Linux的关系
虽然 Android 基于 Linux 内核,但是它与 Linux 之间还是有很大的差别,比如 Android 在 Linux 内核的基础上添加了自己所特有的驱动程序.
1.1.1选择Linux内核
Android 选择采用 Linux 内核是依据 Linux 的一 些特性,比如:
(1)强大的内存管理和进程管理方案
(2)基于权限的安全模式
(3)支持共享库
(4)经过认证的驱动模型
(5)Linux 本身就是开源项目
更多关于上述特性的信息可以参考 Linux 2.6 版内核的官方文档,这便于我们在后面的学 习中更好地理解 Android 所特有的功能特性。接下来分析 Android 与 Linux 的关系。
1.1.2 Android 不是 Linux
Android 是基于 Linux 内核,但Android不是Linux是基于以下几个要点:
(1)没有本地窗口系统
(2)没有 glibc 的支持
(3)并不包括一整套标准的 Linux 使用程序
(4)增强了 Linux 以支持其特有的驱动
1.没有本地窗口系统
本地窗口系统是指 GNU/Linux 上的 X 窗口系统,或者 Mac OX X的 Quartz 等。
不同的操作系统的窗口系统可能不一样,Android 并没有使用(也不需要使用)
Linux 的 X 窗口系统,这是 Android 不是 Linux 的一个基本原因。
2.它没有 glibc 支持
由于 Android 最初用于一些便携的移动设备上,所以,可能出于效率等方面的考虑,Android
并没有采用 glibc 作为 C 库,而是 Google 自己开发了一套 Bionic Libc 来代替 glibc。
3.它并不包括一整套标准的 Linux 使用程序
Android 并没有完全照搬 Liunx 系统的内核,除了修正部分 Liunx 的 Bug 之外,还增加了
不少内容,比如:它基于 ARM 构架增加的 Gold-Fish 平台,以及 yaffs2 FLASH 文件系统等。
4.Android 专有的驱动程序
除了上面这些不同点之外,Android 还对 Linux 设备驱动进行了增强,主要如下所示。
1)Android Binder 基于 OpenBinder 框架的一个驱动,用于提供 Android 平台的进程间通信(InterProcess Communication,IPC)功能。源代码位于 drivers/staging/android/binder.c。
2)Android 电源管理(PM) 一个基于标准 Linux 电源管理系统的轻量级 Android 电源管理驱动,针对嵌入式设备做了很多优化。源代码位于:
kernel/power/earlysuspend.c
kernel/power/consoleearlysuspend.c
kernel/power/fbearlysuspend.c
kernel/power/wakelock.c
kernel/power/userwakelock.c
3)低内存管理器(Low Memory Killer) 比 Linux 的标准的 OOM(Out Of Memory)机
制更加灵 活 ,它可以 根 据需要杀 死 进程以释 放 需要的内 存 。源代码 位 于 drivers/staging/
android/lowmemorykiller.c。
4)匿名共享内存(Ashmem) 为进程间提供大块共享内存,同时为内核提供回收和管 理这个内存的机制。源代码位于 mm/ashmem.c。
5)Android PMEM(Physical) PMEM 用于向用户空间提供连续的物理内存区域,DSP
和某些设备只能工作在连续的物理内存上。源代码位于 drivers/misc/pmem.c。
6)Android Logger 一个轻量级的日志设备,用于抓取 Android 系统的各种日志。源代码位于 drivers/staging/android/logger.c。
7)Android Alarm 提供了一个定时器,用于把设备从睡眠状态唤醒,同时它还提供了一 个即使在设备睡眠时也会运行的时钟基准。源代码位于 drivers/rtc/alarm.c。
8)USB Gadget驱动 一个基于标准Linux USB gadget 驱动框架的设备驱动,Android 的
USB 驱动是基于 gaeget 框架的。源代码位于 drivers/usb/gadget/。
9)Android Ram Console 为了提供调试功能,Android 允许将调试日志信息写入一个被称为RAM Console 的设备里,它是一个基于RAM的Buffer。源代码位于 drivers/staging/android / ram_console.c。
10)Android timed device 提供了对设备进行定时控制的功能,目前支持 vibrator 和 LED
设备。源代码位于 drivers/staging/android /timed_output.c(timed_gpio.c)。
11) Yaffs2 文件系统 Android 采用 Yaffs2 作为 MTD nand flash 文件系统,
源代码于fs/yaffs2/目录下。Yaffs2 是一个快速稳定的应用于 NAND 和 NOR Flash 的跨平台的嵌入式设备文件系统,同其他 Flash 文件系统相比,Yaffs2 能使用更小的内存来保存其运行状态,因此它占用内存小。Yaffs2 的垃圾回收非常简单而且快速,因此能表现出更好的性能。Yaffs2 在大容 量的 NAND Flash 上的性能表现尤为突出,非常适合大容量的 Flash 存储。
上面这些要点足以说明 Android 不是 Linux。 但 Android 对 Linux 内核进行了一些改
动,在移植时就需要对这些改动加以调整。
1.2 Android 对 Linux 内核的改动
Android 从多个方面对 Linux 内核进行了改动与增强,下面将对此进行详细介绍和分析。
1.2.1 Goldfish
Android 模拟器通过运行一个 Goldfish 的虚拟 CPU.Goldfish 来运行 arm926t 指令集(arm926t 属于 armv5 构架),并且仿真了输入/输出,比如键盘输入和 LCD 输出。这个模拟器其实是在 qemu 之上开发的,输入/输出是基于 libSDL 的。既然 Goldfish 是被模拟器运行的虚拟 CPU, 那么当 Android 在真实的硬件设备上运行时,我们就需要去掉它,因此,只有知道 Google 对 Goldfish 做了哪些具体改动之后才能正确地去掉。据统计,Android 内核对 Goldfish 的改动主 要涉及 44 个文件。
1.2.2YAFFS2
不同于 PC 机(文件是存储在硬盘上的),手机使用 FLASH 作为存储介质。HTC 的 G1 使 用的是 NANDFLASH——这种存储目前已经相当普及了,而且种类也颇多(如 SLC、MLC 等), 存储密度也越来越高(已经出现几十 GB 大小的 NANDFLASH),价格也越来越低。
YAFFS2 是专门用在 FLASH 上的文件系统,YAFFS2 是“Yet Another Flash File System,
2nd edition”的缩写。YAFFS2 为 Linux 内核提供了一个高效访问 NANDFLASH 的接口。但是 NANDFLASH 的支持并 不包含在标 准的 2.6.25 内核中,所 以 Google 在其中添加 了对 NANDFLASH 的支持。据统计,为了支持 YAFFS2,Google 一共改动和增加了以下 35 个文件:
1.2.3 蓝牙
在蓝牙通信协议栈里 Google 修改了 10 个文件。这些改动修复了一些与蓝牙耳机相关的明显的 Bug,以及一些与蓝牙调试和访问控制相关的函数,具体如下所示。
1.2.4 调度器(Scheduler)
Android 内核还修改了与进程调度和时钟相关的策略。只改动了 5 个文件,如下:
1
Chg
kernel/sched.c
添加 NORMALIZED_SLEEPER
2
Chg
kernel/sched_fair.c
修改内核的调度方式
3
Chg
kernel/softirq.c
修改为 CPU 调度
4
Chg
kernel/time/tick-sched.c
修改为 CPU 调度
5
Chg
include/linux/tick.h
如果 CONFIG_NO_HZ 被 定义, 则添加 tick_nohz_ update_ stopped_
sched_tick()
1.2.5 Android 新增的驱动
Android 在 Linux 的基础上新增了许多特有的驱动,如下所示。
1)IPC Binder 一种 IPC(进程间通信)机制。它的进程能够为其他进程提供服务——通过标准的 Linux 系统调用 API。IPC Binder 的概念起源于一家名为 Be.Inc 的公司,在 Google 之 前就已经被 Palm 软件采用了。
2)Low Memory Killer 其实内核里已经有一个类似的功能,名称为 oom killer(out of memory killer)。当内存不够的时候,该策略会试图结束一个进程。
3)Ashmem 匿名共享内存。该功能使得进程间能够共享大块的内存。比如说,系统 可以使用 Ashmem 保存一些图标,多个应用程序可以访问这个共享内存来获取这些图标。 Ashmem 为内核提供了一种回收这些使用完的共享内存块的方法,如果某个进程试图访问这些已经被回收的内存块,它将会得到错误的返回值,以便它重新进行内存块分配和数据初始化。
4)RAM Console and Log Device 为了调试方便,Android 添加了一个功能,使调试信 息可以输入到一个内存块中。此外,Android 还添加了一个独立的日志模块,这样用户空间的 进程就能够读写日志消息,以及调试打印信息等。
5)Android Debug Bridge 嵌入式设备的调试的确比较麻烦,为了便于调试,Google 设 计了这个调试工具,可以简称为 ADB,使用 USB 作为连接方式,ADB 可以看做是连接 Android 设备和 PC 机的一套协议。
除了这些主要的功能之外,Android 还增加了诸如 real-time clock、switch、timed GPIO 等 功能,所有这些改动和增加包含在以下 28 个文件之中。
1
Chg
drivers/Kconfig
进入配置文件
2
Chg
drivers/Makefile
添加 switch,驱动等
3
New
drivers/android/Kconfig
添加 BINDER_IPC 、 POWER 、 POWER_STAT 、 POWER_ ALARM 、
4
New
drivers/android/Makefile
添加 binder.o、power.o、alarm.o、logger.o、ram_console.o、timed_gpio
5
New
drivers/android/alarm.c
系统硬件时钟和实时时钟管理
6
New
drivers/android/binder.c
IPC 机制(Binder)
7
New
drivers/android/logger.c
Google 的日志 API
8
New
drivers/android/ram_console.c
RAM 控制台和日志设备方便调试
9
New
drivers/android/timed_gpio.c
Google 的 GPIO 定时驱动
10
New
drivers/switch/Kconfig
为 GPIO 添加配置选项
11
New
drivers/switch/Makefile
引入 GPIO 驱动
12
New
drivers/switch/switch_class.c
13
New
drivers/switch/switch_gpio.c
14
Chg
drivers/usb/gadget/Kconfig
添加 ADB 配置选项
15
Chg
drivers/usb/gadget/Makefile
编译 ADB 所需的配置选项
16
New
drivers/usb/gadget/android_adb.c
ADB 驱动
17
New
include/linux/android_aid.h
添加 AIDs、INET、networking
18
New
include/linux/android_alarm.h
时钟功能设置
19
New
include/linux/android_timed_gpio.h
GPIO 结构体
20
New
include/linux/ashmem.h
Android 共享内存
21
New
include/linux/binder.h
Binder IPC API 定义
22
New
include/linux/logger.h
Logger 定义
23
New
include/linux/switch.h
GPIO switch 接口
24
Chg
mm/Makefile
添加 ashmem.o
25
New
mm/ashmem.c
内存共享实现
26
Chg
drivers/misc/Kconfig
添加 LOW_MEMORY_KILLER 配置选项
27
Chg
drivers/misc/Makefile
添加 lowmemorykiller.c
28
New
drivers/misc/lowmemorykiller.c
当内存过低时,选择并结束进程
1.2.6 电源管理
电源管理(Power Management)对于移动设备来说相当重要,也是最为复杂和开发难度最 高的一个功能。Google 添加了一个新的电源管理系统,不包含原有的 apm 和 dpm 等。这项改 动主要涉及以下 5 个文件:
1
New
include/linux/android_power.h
定义电源管理 API
2
New
drivers/android/power.c
电源管理 API 实现
3
Chg
drivers/input/evdev.c
修改 Android 电源处理方式
4
Chg
fs/inotify_user.c
修改 Android 电源处理方式
5
Chg
kernel/power/process.c
修改 Android 电源处理方式
1.2.7 杂项
除了上述改动之外,还有一些小改动,如新增的额外调试功能、键盘背光控制、TCP 网络 管理等,共涉及 36 个文件,如下所示
1
New
Documentation/vm/pagemap.txt
2
Chg
arch/arm/Kconfig
添加 HAVE_LATENCYTOP_SUPPORT 和 ARCH_GOLDFISH
3
Chg
arch/arm/kernel/process.c
添加 dump_task_regs 方法
4
Chg
arch/arm/kernel/signal.c
解决系统无法重新启动的问题
5
Chg
arch/arm/kernel/stacktrace.c
改进调试栈跟踪
6
Chg
arch/arm/mm/abort-ev6.S
7
Chg
drivers/char/Kconfig
添加 Memory device driver 和 Goldfish TTY driver
8
Chg
drivers/char/mem.c
使编译结果输出到/dev/kmem and /dev/mem
9
Chg
drivers/leds/Kconfig
当 CPU 运行时打开 LEDS,但是屏幕是关闭的
10
Chg
drivers/leds/Makefile
添加编译 ledtrig-sleep.o
11
New
drivers/leds/ledtrig-sleep.c
睡眠(当关闭屏幕后 CPU 仍然运行)
12
Chg
drivers/rtc/class.c
修正实时时钟误差的 Bug
13
Chg
fs/fat/dir.c
添加 VFAT_IOCTL_GET_VOLUME_ID 到 fat_dir_ioctl()
14
Chg
fs/fat/inode.c
15
Chg
fs/proc/base.c
当内存不足时调整/proc 文件
16
Chg
fs/proc/proc_misc.c
修正 kpagecount_read 和 kpageflags_read 返回的一些错误
17
Chg
fs/proc/task_mmu.c
简化 add_to_pagemap 中的错误检查
18
Chg
include/asm-arm/elf.h
添加 ELF_CORE_COPY_TASK_REGS()宏调用 dump_task_ regs(...)
19
Chg
include/linux/mm.h
添加 shmem_set_file(...)函数原型
20
Chg
include/linux/msdos_fs.h
添加 VFAT_IOCTL_GET_VOLUME_ID 宏
21
Chg
kernel/hrtimer.c
修复 run_hrtimer_pending 错误
22
Chg
init/Kconfig
添加 PANIC_TIMEOUT 默认为 0
23
Chg
kernel/panic.c
设置默认的 panic_timeout:从 kernel 配置到 PANIC_TIMEOUT
24
Chg
kernel/power/console.c
修复虚拟控制台的错误信息
25
Chg
kernel/printk.c
修复 printk 错误
26
Chg
mm/filemap.c
修正 filemap_fault
27
Chg
mm/shmmem.c
重构 shmem_zero_setup
28
Chg
mm/tiny-shmem.c
重构 shmem_zero_setup
29
Chg
include/linux/sockios.h
添加 SIOCKILLADDR 控制
30
Chg
include/net/tcp.h
添加 tcp_v4_nuke_addr 函数
31
Chg
net/ipv4/Makefile
如果设置 CONFIG_SYSFS,编译 sysfs_net_ipv4
32
Chg
net/ipv4/af_inet_c
如果定义 CONFIG_ANDROID_PARANOID_NETWORK,则添加安全检查
33
Chg
net/ipv4/devinet.c
添加 SIOCKILLADDR
34
Chg
net/ipv4/sysfs_net_ipv4.c
控制 TCP 窗口长度
35
Chg
net/ipv4/tcp_ipv4.c
添加 tcp_v4_nuke_addr 函数
36
Chg
net/ipv6/af_inet6.c
如果定义 CONFIG_ANDROID_PARANOID_NETWORK,则添加安全检查
上面这些看似简单,但是非常重要,当大家进行系统级应用开发和程序移植时都需要研究
这些文件。对于每个文件的具体改动方式和实现,我们需要进一步查看 Android 的内核源代码, 这是后面将要详细讲解的内容。
1.3Android 对 Linux 内核的增强
1.2 节介绍了 Android 对 Linux 内核的改动,这一节将重点介绍 Android 对 Linux 内核的增强,主要包括 Alarm(硬件时钟)、Ashmem(匿名内存共享)、Low Memory Killer(低内存管 理)、Logger(日志设备),等等。
1.3.1 Alarm(硬件时钟)
Alarm 就是一个硬件时钟,前面我们已经知道它提供了一个定时器,用于把设备从睡眠状态唤醒,同时它也提供了一个在设备睡眠时仍然会运行的时钟基准。在应用层上,有关时间的应用都需要 Alarm 的支持,源代码位于“drivers/rtc/alarm.c”。
Alarm 的设备名为“/dev/alarm”。该设备的实现非常简单,我们首先打开源码,可以看到
include <linux/android_alarm.h>,其中定义了一些 Alarm 的相关信息。Alarm 的类型枚举如下:
enum android_alarm_type { ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, ANDROID_ALARM_ELAPSED_REALTIME, ANDROID_ALARM_SYSTEMTIME, ANDROID_ALARM_TYPE_COUNT,
};
主要包括了 5 种类型的 Alarm,_WAKEUP 类型表示在触发 Alarm 时需要唤醒设备,反之 则不需要唤醒设备; ANDROID_ALARM_RTC 类型表示在指定的某一时刻出发 Alarm ; ANDROID_ALARM_ELAPSED_REALTIME 表示在设备启动后,流逝的时间达到总时间之后触发 Alarm;ANDROID_ALARM_SYSTEMTIME 类型则表示系统时间;ANDROID_ALARM_ TYPE_COUNT 则是 Alram 类型的计数。
Alarm 返回标记的枚举类型如下:
enum android_alarm_return_flags {
ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK =
1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, ANDROID_ALARM_ELAPSED_REALTIME_MASK =
1U << ANDROID_ALARM_ELAPSED_REALTIME,
ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME, ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
};
Alarm 返回标记会随着 Alarm 的类型而改变。最后还定义了一些宏,主要包括禁用 Alarm、
Alarm 等待、设置 Alarm 等。下面我们来分析 Alarm 驱动的具体实现。
首先,Alarm 的初始化及退出由以下三个函数来完成:
late_initcall(alarm_late_init);
module_init(alarm_init);
module_exit(alarm_exit);
其中 alarm_init 函数对 Alarm 执行初始化操作,alarm_late_init 需要在初始化完成之后进行
调用,最后退出时需要调用 alarm_exit 来销毁和卸载 Alarm 接口及驱动。
1.alarm_init
在初始化过程中,首先需要初始化系统时间,通过 platform_driver_register 函数来注册 Alarm
驱动的相关参数,具体如下所示:
static struct platform_driver alarm_driver = {
.suspend = alarm_suspend,
.resume = alarm_resume,
.driver = {
.name = "alarm"
}
};
该参数 主要指定了 当系统挂起 ( suspend )和唤醒( Desume )所需 要实现的分 别为
alarm_suspend 和 alarm_resume,同时将 Alarm 设备驱动的名称设置为了“alarm”。 如果设置正确,那么继续通过如下代码来初始化 SUSPEND lock,因为在使用它们之前必
须执行初始化操作。
wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm");
wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc");
紧接着通过 class_interface_register 函数来注册 Alarm 接口信息,主要包括设备的添加和移除操作,内容如下:
static struct class_interface rtc_alarm_interface = {
.add_dev = &rtc_alarm_add_device,
.remove_dev = &rtc_alarm_remove_device,
};
如果在此过程中出现错误,那么需要销毁已经注册的 SUSPEND lock,并且卸载 Alarm 驱 动,代码如下:
wake_lock_destroy(&alarm_rtc_wake_lock); wake_lock_destroy(&alarm_wake_lock); platform_driver_unregister(&alarm_drive r);
该锁可以被用户态程序和内核获得。这个锁可以是超时的或者是没有超时的,超时
的锁会在时间过期以后自动解锁。如果没有锁或者超时了,内核就会启动休眠机制
2.alarm_late_init
当Alarm启动之后,我们需要读取当前的 RCT 和系统时间,由于需要确保在这个操作过
程中不被中断,或者在中断之后能告诉其他进程该过程没有读取完成,不能被请求,因此这 里需要通过 spin_lock_irqsave 和 spin_unlock_irqrestore 来对其执行锁定和解锁操作。实现代 码如下:
static int __init alarm_late_init(void)
{
unsigned long flags;
struct timespec system_time;
spin_lock_irqsave(&alarm_slock, flags);
getnstimeofday(&elapsed_rtc_delta);
ktime_get_ts(&system_time);
elapsed_rtc_delta = timespec_sub(elapsed_rtc_delta, system_time);
spin_unlock_irqrestore(&alarm_slock, flags);
ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO,
"alarm_late_init: rtc to elapsed realtime delta %ld.%09ld\n", elapsed_rtc_delta.tv_sec, elapsed_rtc_delta.tv_nsec);
return 0;
}
3.alarm_exit
当 Alarm 退出时,就需要通过 class_interface_unregister 函数来卸载在初始化时注册的 Alarm
接口,通过 wake_lock_destroy 函数来销毁 SUSPEND lock,以及通过 platform_driver_unregister
函数来卸载 Alarm 驱动。实现代码如下:
static void __exit alarm_exit(void)
{
class_interface_unregister(&rtc_alarm_interface); wake_lock_destroy(&alarm_rtc_wake_lock); wake_lock_destroy(&alarm_wake_lock); platform_driver_unregister(&alarm_driver);
}
4.添加和移除设备
接下来是 rtc_alarm_add_device 和 rtc_alarm_remove_device 函数的实现。添加设备时,首先 将设备转换成 rtc_device 类型,然后,通过 misc_register 函数将自己注册成为一个 Misc 设备。 其包括的主要特性如下面的代码所示:
static struct file_operations alarm_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = alarm_ioctl,
.open = alarm_open,
.release = alarm_release,
};
static struct miscdevice alarm_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "alarm",
.fops = &alarm_fops,
};
其中 alarm_device 中的“.name”表示设备文件名称,而 alarm_fops 则定义了 Alarm 的常用操作,包括打开、释放和 I/O 控制。这里还需要通过 rtc_irq_register 函数注册一个 rtc_task, 用来处理 Alarm 触发的方法,其定义如下:
static struct rtc_task alarm_rtc_task = {
.func = alarm_triggered_func
};
其中“alarm_triggered_func”则是 Alarm 需要触发的方法。
销毁和卸载。但是,移除一个设备时同样需要判断设备是否是Alarm 设备,
然后再执行卸载等操作。另外,在处理挂起操作时,我们首先就需要对设备
进行锁定,然后根据 Alarm 的类型执行不同的操作,同时要保存时间。
alarm_open 和 alarm_release 的实现很简单。最后需要说明的是,对于 I/O 操作而言,主要
需要实现:设置时间、设置 RTC、获取时间、设置 Alarm 等待等。
本小节主要对 Android 中最简单的设备驱动——Alarm的实现流程进行了分析,大家应该
可以 自己绘制出 一个流程图 来了吧。对 于Alarm的 具 体实现,大家可以参考源代码
“drivers/rtc/alarm.c”中的实现方式。
1.3.2 Ashmem(匿名内存共享)
Ashmem 是 Android 的内存分配与共享机制,它在 dev 目录下对应的设备文件为/dev/ashmem, 其实现的源文件为:
include/linux/ashmem.h
kernel/mm/ashmem.c
相比于 malloc 和 anonymous/named mmap 等传统的内存分配机制,其优势是通过内核驱动
提供了辅助内核的内存回收算法机制(pin/unpin)。什么是 pin 和 unpin 呢?具体来讲,就是当 你使用 Ashmem 分配了一块内存,但是其中某些部分却不会被使用时,那么就可以将这块内存 unpin 掉。unpin 后,内核可以将它对应的物理页面回收,以作他用。你也不用担心进程无法对unpin 掉的内存进行再次访问,因为回收后的内存还可以再次被获得(通过缺页 handler),因为 unpin 操作并不会改变已经 mmap 的地址空间。下面就来分析 Ashmem 的内核驱动是如何完成 这些功能。
首先,打开其头文件(ashmem.h),可以看到定义了以下一些宏和结构体:
//设备文件名称
#define ASHMEM_NAME_DEF "dev/ashmem"
//从 ASHMEM_PIN 返回的值,判断是否需要清楚
#define ASHMEM_NOT_PURGED 0
#define ASHMEM_WAS_PURGED 1
//从 ASHMEM_GET_PIN_STATUS 返回的值,判断是 pin 还是 unpin
#define ASHMEM_IS_UNPINNED0
#define ASHMEM_IS_PINNED 1
struct ashmem_pin {
__u32 offset;//在 Ashmem 区域的偏移量
__u32 len; //从偏移量开始的长度
};
另外一些宏用于设置 Ashmem 的名称和状态,以及 pin 和 unpin 等操作。接下来看一下 Ashmem 的具体实现,打开(ashmem.c)文件,首先大致预览一下它有哪些功能函数,如图 2-1 所示。
展开阅读全文