android电源管理kernel部分学习

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);
}

  

(锁机制将以后分析,待续.....)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值