kernel版本:2.6.36
android版本:2.3.4
硬件平台:mini6410
文件路径kernel/power/main.c
一、 向内核注册
static int __init pm_init(void)
{
int error = pm_start_workqueue(); //创建开始工作队列,为后面冻结进程等相关工作创建队列 --><pre name="code" class="cpp">
<span style="color:#3333ff;background-color: rgb(255, 255, 255);">static int __init pm_start_workqueue(void)
{ //此部分是</span><span style="background-color: rgb(255, 255, 255); color: rgb(51, 51, 255); font-family: Arial, Helvetica, sans-serif;">pm_start_workqueue 函数原型</span><span style="color:#3333ff;background-color: rgb(255, 255, 255);">
pm_wq = create_freezeable_workqueue("pm");
return pm_wq ? 0 : -ENOMEM;
}</span>
if (error)return error;power_kobj = kobject_create_and_add("power", NULL); // 创建power kobjectif (!power_kobj)return -ENOMEM;return sysfs_create_group(power_kobj, &attr_group); // 创建sysfs文件接口图组}core_initcall(pm_init); // 向内核注册pm驱动
二、 编写sysfs接口文件 sysfs_create_group
static struct attribute * g[] = {
&state_attr.attr,
#ifdef CONFIG_PM_TRACE //次宏未定义
&pm_trace_attr.attr,
#endif
#ifdef CONFIG_PM_SLEEP
&pm_async_attr.attr,
&wakeup_count_attr.attr,
#ifdef CONFIG_PM_DEBUG
&pm_test_attr.attr,
#endif
#ifdef CONFIG_USER_WAKELOCK
&wake_lock_attr.attr,
&wake_unlock_attr.attr,
#endif
#endif
NULL,
};
static struct attribute_group attr_group = {
.attrs = g,
};
<span style="background-color: rgb(255, 255, 255);"> <span style="color:#ff0000;">由上代码可以发现将在sys/power/下面创建state pm_async pm_test wake_lock wake_unlock文件, 一下主要分析</span><span style="color:#3333ff;">state</span><span style="color:#ff0000;">、</span><span style="color:#000099;">wake_lock</span><span style="color:#ff0000;">和</span><span style="color:#000099;">wake_unlock</span><span style="color:#ff0000;">文件接口</span></span>
2.1 state_show和state_store
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
char *s = buf;
#ifdef CONFIG_SUSPEND
int i;
for (i = 0; i < PM_SUSPEND_MAX; i++) {
if (pm_states[i] && valid_state(i))
s += sprintf(s,"%s ", pm_states[i]);
}
#endif
#ifdef CONFIG_HIBERNATION
s += sprintf(s, "%s\n", "disk");
#else
if (s != buf)
/* convert the last space to a newline */
*(s-1) = '\n';
#endif
return (s - buf); //返回有哪些状态可以操作
}
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
#ifdef CONFIG_SUSPEND
#ifdef CONFIG_EARLYSUSPEND
suspend_state_t state = PM_SUSPEND_ON;
#else
suspend_state_t state = PM_SUSPEND_STANDBY;
#endif
const char * const *s;
#endif
char *p;
int len;
int error = -EINVAL;
p = memchr(buf, '\n', n);
len = p ? p - buf : n;
/* First, check if we are requested to hibernate */
if (len == 4 && !strncmp(buf, "disk", len)) {
error = hibernate();
goto Exit;
}
#ifdef CONFIG_SUSPEND
for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
break;
}
if (state < PM_SUSPEND_MAX && *s)
#ifdef CONFIG_EARLYSUSPEND //此宏也定义故程序会走<span style="font-family: Arial, Helvetica, sans-serif;">request_suspend_state 函数</span>
if (state == PM_SUSPEND_ON || valid_state(state)) {
error = 0;
<span style="color:#ff0000;">request_suspend_state(state)</span>;
}
#else
error = enter_state(state);
#endif
#endif
Exit:
return error ? error : n;
}
2.2 request_suspend_state函数原型
void request_suspend_state(suspend_state_t new_state)
{
unsigned long irqflags;
int old_sleep;
spin_lock_irqsave(&state_lock, irqflags);
old_sleep = state & SUSPEND_REQUESTED;
if (debug_mask & DEBUG_USER_STATE) {
struct timespec ts;
struct rtc_time tm;
getnstimeofday(&ts);
rtc_time_to_tm(ts.tv_sec, &tm);
pr_info("request_suspend_state: %s (%d->%d) at %lld "
"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
requested_suspend_state, new_state,
ktime_to_ns(ktime_get()),
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
}
if (!old_sleep && new_state != PM_SUSPEND_ON) {
state |= SUSPEND_REQUESTED;
queue_work(suspend_work_queue, &early_suspend_work);<span style="color:#3333ff;"> //电源睡眠将调用early_suspend工作队列</span>
} else if (old_sleep && new_state == PM_SUSPEND_ON) {
state &= ~SUSPEND_REQUESTED;
wake_lock(&main_wake_lock);
queue_work(suspend_work_queue, &late_resume_work); <span style="font-family: Arial, Helvetica, sans-serif;">/<span style="color:#3333ff;">/电源唤醒将调用late_resume工作队列</span></span>
}
requested_suspend_state = new_state; <span style="color:#3366ff;">//更新状态</span>
spin_unlock_irqrestore(&state_lock, irqflags);
}
2.3 early_suspend函数原型
static void early_suspend(struct work_struct *work)
{
struct early_suspend *pos;
unsigned long irqflags;
int abort = 0;
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPEND_REQUESTED)
state |= SUSPENDED;
else
abort = 1;
spin_unlock_irqrestore(&state_lock, irqflags);
if (abort) {
if (debug_mask & DEBUG_SUSPEND)
pr_info("early_suspend: abort, state %d\n", state);
mutex_unlock(&early_suspend_lock);
goto abort;
}
if (debug_mask & DEBUG_SUSPEND)
pr_info("early_suspend: call handlers\n");
list_for_each_entry(pos, &early_suspend_handlers, link) { <span style="color:#ff0000;">//遍历所有驱动加入的电源管理函数,</span>
if (pos->suspend != NULL)
pos->suspend(pos); //<span style="color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif;">调用所有suspend函数</span>
}
mutex_unlock(&early_suspend_lock);
if (debug_mask & DEBUG_SUSPEND)
pr_info("early_suspend: sync\n");
sys_sync();
abort:
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
wake_unlock(&main_wake_lock); <span style="color:#ff0000;">//此步将去释放唤醒锁,该锁机制是google为android特别添加的一种锁机制</span>
spin_unlock_irqrestore(&state_lock, irqflags);
}
(锁机制将以后分析,待续.....)