Android Alarm驱动源代码分析(Alarm.c)

 

前言:

Android在Linux Kernel的基础上增加了很多的驱动程序,Alarm驱动是其中最简单的一个,整个文件只有500多行。作为驱动代码分析的一系列文章的开始,我试图仔细的分析此驱动的几乎所有函数代码,希望籍此作为温习Android驱动源代码一个良好的开端。

Android的增加了一个Alarm驱动,在kernel_root/driver/rtc/alarm.c文件中实现。Android希望提供一种递增的时钟(monotonic ),此时钟应基于硬件,使得Android的应用程序能够在设备进入休眠状态的时候,仍然运行或者唤醒设备,以此达到节电的目的。

 

1.概况

1.1 实现机理

Android Alarm基于硬件时钟,运行在硬中断中。但他本身没有实现硬件RTC的驱动,它是基于Linux高精度时钟hrtimer来实现的。

Linux高精度时钟的实现在kernel_root/kernel/Hrtimer.c文件中。

关于此部分(高精度时钟hrtimer)的分析可以参见如下两篇别人的博文:

http://blog.csdn.net/walkingman321/article/details/6133171

http://blog.csdn.net/walkingman321/article/details/6151172

 

1.2实现方式

Alarm.c在Linux Kernel中注册了一个平台设备(最终注册了一个RTC设备,保存在变量static struct rtc_device *alarm_rtc_dev;中),设备节点为/dev/alarm。

用户空间的程序通过fopen打开此节点还获得控制句柄,然后通过ioctrl来向此驱动程序发送请求。

如下文件直接使用了此驱动:

android_root/system/core/toolbox/alarm.c

android_root/frameworks/base/serices/jni/com_android_server_AlarmManagerService.cpp

android_root/system/core/toolbox/Date.c

android_root/frameworks/base/cmds/runtime/Main_runtime.cpp

android_root/frameworks/base/libs/utils/SystemClock.cpp

android_root/system/core/toolbox/Uptime.c

 

1.3使用Alarm驱动的Demo代码

如果你需要直接操作此驱动,可以参考上面文件中的使用方法。

如下示例摘自SystemClock.cpp:

#if HAVE_ANDROID_OS
    fd = open("/dev/alarm", O_RDWR);
    if(fd < 0) {
        LOGW("Unable to open alarm driver: %s\n", strerror(errno));
        return -1;
    }
    ts.tv_sec = tv.tv_sec;
    ts.tv_nsec = tv.tv_usec * 1000;
    res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
    if(res < 0) {
        LOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
        ret = -1;
    }
    close(fd);
#else
    if (settimeofday(&tv, NULL) != 0) {
        LOGW("Unable to set clock to %d.%d: %s\n",
            (int) tv.tv_sec, (int) tv.tv_usec, strerror(errno));
        ret = -1;
    }
#endif

 

2.驱动代码分析

2.1 主要函数清单

alarm_start_hrtimer 工具函数,alarm驱动的其他函数通过此函数为对应类型(android_alarm_type)的Alarm建立一个hrtimer定时器。

alarm_ioctl alarm驱动的ioctl函数,上层代码通过此接口向驱动程序发送操作请求。

alarm_open

alarm_release

alarm_timer_triggered

alarm_triggered_func

alarm_suspend

alarm_resume

rtc_alarm_add_device

rtc_alarm_remove_device

alarm_late_init 驱动的后置初始化函数,在alarm_init后运行(参见本节的备注)。

alarm_init 驱动的初始化函数

alarm_exit 驱动的退出函数

 

备注: 关于Linux驱动程序的启动顺序(alarm_init 和alarm_late_init)的相关说明,请参见如下博文:

http://blog.csdn.net/cstk502/article/details/6579231

 

2.2 alarm_start_hrtimer 函数

 代码及注释如下:

static void alarm_start_hrtimer(enum android_alarm_type alarm_type)
{
 struct timespec hr_alarm_time;
 if (!(alarm_enabled & (1U << alarm_type))) //根据掩码alarm_enabled来判断此类型的enabled.
  return;
 hr_alarm_time = alarm_time[alarm_type]; //保存该类型的timespec到局部变量
 if (alarm_type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP ||
     alarm_type == ANDROID_ALARM_ELAPSED_REALTIME)
  set_normalized_timespec(&hr_alarm_time,  //设置时间格式
   hr_alarm_time.tv_sec + elapsed_rtc_delta.tv_sec,
   hr_alarm_time.tv_nsec + elapsed_rtc_delta.tv_nsec);

//记录日志,当前版本已经Disable了这个宏,所以不会有日志出现。
 ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW,
  "alarm start hrtimer %d at %ld.%09ld\n",
  alarm_type, hr_alarm_time.tv_sec, hr_alarm_time.tv_nsec);

//为alarm_timer[alarm_type]添加一个hrtimer, 如果alarm_timer[alarm_type]已经存在一个hrtimer,则先删除然后再添加一个新的。请查看hrtimer.c中hrtimer_start_range_ns函数的实现。
 hrtimer_start(&alarm_timer[alarm_type],
        timespec_to_ktime(hr_alarm_time), HRTIMER_MODE_ABS);
}

 

总结:此函数最终为alarm_type类型在数组alarm_timer[alarm_type]上创建了一个hrtimer.

 

2.3 alarm_init函数

 

未完待续。

 

你可能感兴趣的:(android,timer,linux,struct,server,代码分析)