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函數

 

未完待續。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章