2024年6月6日发(作者:)

第十一章 Android内核驱动——Alarm

11.1 基本原理

Alarm 闹钟是 android 系统中在标准 RTC 驱动上开发的一个新的驱动,提供了一个定时器

用于把设备从睡眠状态唤醒,当然因为它是依赖 RTC 驱动的,所以它同时还可以为系统提

供一个掉电下还能运行的实时时钟。

当系统断电时,主板上的rtc芯片将继续维持系统的时间,这样保证再次开机后系统的时间

不会错误。当系统开始时,内核从 RTC 中读取时间来初始化系统时间,关机时便又将系统

时间写回到 rtc 中,关机阶段将有主板上另外的电池来供应 rtc 计时。Android 中的Alarm

在设备处于睡眠模式时仍保持活跃,它可以设置来唤醒设备。

上图为android系统中alarm和rtc驱动的框架。Alarm依赖于rtc驱动框架,但它不是一个 rtc

驱动,主要还是实现定时闹钟的功能。相关源代码在kernel/drivers/rtc/alarm.c和

drivers/rtc/alarm_dev.c。

其中alarm.c文件实现的是所有alarm设备的通用性操作,它创建了一个设备class,而

alarm_dev.c则创建具体的alarm设备,注册到该设备class中。alarm.c还实现了与interface.c

的接口,即建立了与具体rtc驱动和rtc芯片的联系。alarm_dev.c在alarm.c基础包装了一层,

主要是实现了标准的miscdevice接口,提供给应用层调用。

可以这样概括:alarm.c实现的是机制和框架,alarm_dev.c则是实现符合这个框架的设备驱

动,alarm_dev.c相当于在底层硬件rtc闹钟功能的基础上虚拟了多个软件闹钟。

11.2 关键数据结构

 alarm

定义在 include/linux/android_alarm.h 中。

struct alarm {

struct rb_node node;

enum android_alarm_type type;

ktime_t softexpires; //最早的到期时间

ktime_t expires; //绝对到期时间

void (*function)(struct alarm *); //当到期时系统回调该函数

};

这个结构体代表alarm设备,所有的 alarm 设备按照它们过期时间的先后被组织成一

个红黑树,即红黑树的节点,alarm设备通过这个变量插入红黑树。

是类型,android中一共定义了如下 5 种类型,在现在的系统中每种类型只有一个设备。

enum android_alarm_type {

/* return code bit numbers or set alarm arg */

ANDROID_ALARM_RTC_WAKEUP,

ANDROID_ALARM_RTC,

ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,

ANDROID_ALARM_ELAPSED_REALTIME,

ANDROID_ALARM_SYSTEMTIME,

ANDROID_ALARM_TYPE_COUNT,

/* return code bit numbers */

/* ANDROID_ALARM_TIME_CHANGE = 16 */

};

 alarm_queue

struct alarm_queue {

struct rb_root alarms; //红黑树的根

struct rb_node *first; //指向第一个 alarm device,即最早到时的

struct hrtimer timer; //内核定时器,android 利用它来确定 alarm 过期时间

ktime_t delta; //是一个计算 elasped realtime 的修正值

bool stopped;

ktime_t stopped_time;

};

这个结构体用于将前面的 struct alarm 表示的设备组织成红黑树。它是基于内核定时器

来实现 alarm 的到期闹铃的。

11.3 关键代码分析

 alarm_dev.c