- UID
- 1029342
- 性别
- 男
|
//这个poll/select的后端实现, 用于查询有没有数据可读
static unsigned int apm_poll(struct file *fp, poll_table *wait)
{
struct apm_user *as =fp->private_data;
poll_wait(fp,&apm_waitqueue, wait);
returnqueue_empty(&as->queue) ? 0 : POLLIN| POLLRDNORM;
}
//这个是这个设备的核心函数, 用于内核与用户空间交互
static int apm_ioctl(struct inode * inode, struct file *filp, u_intcmd, u_long arg)
{
struct apm_user *as =filp->private_data;
int err = -EINVAL;
//只有超级用户才能执行回复
if (!as->suser|| !as->writer)
return -EPERM;
switch (cmd) {
case APM_IOC_SUSPEND:
mutex_lock(&state_lock);
as->suspend_result = -EINTR;
switch (as->suspend_state) {
//这个就是当user读取到event时的状态,这是发送这个事件,意味着这是回应ack
case SUSPEND_READ:
as->suspend_state= SUSPEND_ACKED;
atomic_dec(&suspend_acks_pending);
mutex_unlock(&state_lock);
wake_up(&apm_suspend_waitqueue);
freezer_do_not_count();
wait_event(apm_suspend_waitqueue,as->suspend_state == SUSPEND_DONE);
freezer_count();
break;
case SUSPEND_ACKTO:
as->suspend_result = -ETIMEDOUT;
mutex_unlock(&state_lock);
break;
default:
as->suspend_state = SUSPEND_WAIT;
mutex_unlock(&state_lock);
as->suspend_result= pm_suspend(PM_SUSPEND_MEM);
}
mutex_lock(&state_lock);
err= as->suspend_result;
as->suspend_state= SUSPEND_NONE;
mutex_unlock(&state_lock);
break;
}
returnerr;
}
3, 事件队列函数
static void queue_event(apm_event_t event)
{
struct apm_user *as;
down_read(&user_list_lock);
list_for_each_entry(as,&apm_user_list, list) {
if (as->reader)
//这个是将这个事件发给每个需要知道事件的apm_user
queue_add_event(&as->queue,event);
}
up_read(&user_list_lock);
//唤醒等待读的进程
wake_up_interruptible(&apm_waitqueue);
}
static void queue_add_event(struct apm_queue *q, apm_event_tevent)
{
q->event_head =(q->event_head + 1) % APM_MAX_EVENTS;
if (q->event_head ==q->event_tail) {
static int notified;
if (notified++ == 0)
printk(KERN_ERR "apm: an event queue overflowed\n");
q->event_tail = (q->event_tail + 1) %APM_MAX_EVENTS;
}
q->events[q->event_head] =event;
}
4,所有用户回复了,可以执行ioctl中的pm_suspend了这部分说明kernel里面的电源管理的核心函数,这部分的代码在/kernel/power/suspend.c中
int pm_suspend(suspend_state_t state)
{
if (state > PM_SUSPEND_ON&& state <=PM_SUSPEND_MAX)
return enter_state(state);
return -EINVAL;
}
调用enter_state(),同样在supend.c中
int enter_state(suspend_state_t state)
{
int error;
if (!valid_state(state))
return-ENODEV;
//获得锁, 参见注释
if(!mutex_trylock(&pm_mutex))
return-EBUSY;
printk(KERN_INFO "PM: Syncing filesystems ...");
sys_sync();
printk("done.\n");
//prepare阶段
pr_debug("PM: Preparing system for %s sleep\n",pm_states[state]);
error = suspend_prepare();
if (error)
goto Unlock;
if(suspend_test(TEST_FREEZER))
goto Finish;
//进入阶段
pr_debug("PM: Entering %s sleep\n",pm_states[state]);
error = suspend_devices_and_enter(state);
//完成挂起, 恢复状态
Finish:
pr_debug("PM: Finishing wakeup.\n");
suspend_finish();
Unlock:
mutex_unlock(&pm_mutex);
return error;
}
4.1准备阶段,为进入supend状态做准备
static int suspend_prepare(void)
{
int error;
if (!suspend_ops ||!suspend_ops->enter)
return -EPERM;
//allocate a console
pm_prepare_console();
//Run suspend notifiers
error =pm_notifier_call_chain(PM_SUSPEND_PREPARE);
if (error)
goto Finish;
error =usermodehelper_disable();
if (error)
goto Finish;
//进程处理
error =suspend_freeze_processes();
if (!error)
return 0;
suspend_thaw_processes();
usermodehelper_enable();
Finish:
pm_notifier_call_chain(PM_POST_SUSPEND);
pm_restore_console();
return error;
} |
|