Chinaunix首页 | 论坛 | 博客
  • 博客访问: 64198
  • 博文数量: 23
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 15
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-24 23:15
文章分类

全部博文(23)

文章存档

2014年(3)

2013年(20)

我的朋友

分类: LINUX

2013-07-19 15:47:12

原文地址:PM notifier 作者:stanleymiao

PM定义了一个notifier_chain:

 27 static BLOCKING_NOTIFIER_HEAD(pm_chain_head);

PM在休眠和唤醒的过程中会发出一些EVENTS,

246 /* Hibernation and suspend events */
247 #define PM_HIBERNATION_PREPARE  0x0001 /* Going to hibernate */
248 #define PM_POST_HIBERNATION     0x0002 /* Hibernation finished */
249 #define PM_SUSPEND_PREPARE      0x0003 /* Going to suspend the system */
250 #define PM_POST_SUSPEND         0x0004 /* Suspend finished */
251 #define PM_RESTORE_PREPARE      0x0005 /* Going to restore a saved image */
252 #define PM_POST_RESTORE         0x0006 /* Restore failed */

如果哪个内核模块想得到这些EVENTS,就需要定义一个notifier_block, 并把它挂载到pm_chain_head上。为此,PM定义了挂载和卸载函数:

 29 int register_pm_notifier(struct notifier_block *nb)
 30 {
 31         return blocking_notifier_chain_register(&pm_chain_head, nb);
 32 }
 33 EXPORT_SYMBOL_GPL(register_pm_notifier);
 34
 35 int unregister_pm_notifier(struct notifier_block *nb)
 36 {
 37         return blocking_notifier_chain_unregister(&pm_chain_head, nb);
 38 }
 39 EXPORT_SYMBOL_GPL(unregister_pm_notifier);

在PM休眠或者唤醒进行到某个特定阶段时,PM就会使用下面这个函数向链上所有的内核模块发送一个EVENT。

 41 int pm_notifier_call_chain(unsigned long val)
 42 {
 43         return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
 44                         == NOTIFY_BAD) ? -EINVAL : 0;
 45 }

比如, 我们可以在suspend_prepare()中发现这样的代码:

 88         error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
 89         if (error)
 90                 goto Finish;
 91   
 
102  Finish:
103         pm_notifier_call_chain(PM_POST_SUSPEND);


我们可以在vmwatchdog.c中看到使用pm_chain的例子。

vmwatchdog想获得下面的四个EVENTS,

PM_POST_HIBERNATION
PM_POST_SUSPEND
PM_HIBERNATION_PREPARE
PM_SUSPEND_PREPARE:

并在这4个EVENTS发生时调用对应的函数。 于是它定义了vmwdt_power_event()函数:

272 /*
273  * This function is called for suspend and resume.
274  */
275 static int vmwdt_power_event(struct notifier_block *this, unsigned long event,
276                              void *ptr)
277 { 
278         switch (event) {
279         case PM_POST_HIBERNATION:
280         case PM_POST_SUSPEND:      
281                 return vmwdt_resume();
282         case PM_HIBERNATION_PREPARE:
283         case PM_SUSPEND_PREPARE:
284                 return vmwdt_suspend();
285         default:
286                 return NOTIFY_DONE;
287         }
288 } 

vmwatch定义了一个notifier_block结构,叫做vmwdt_power_notifier,

290 static struct notifier_block vmwdt_power_notifier = {
291         .notifier_call = vmwdt_power_event,
292 };

并把它挂载到pm_chain链上,

315         ret = register_pm_notifier(&vmwdt_power_notifier);

这样,每次PM通过pm_notifier_call_chain()发出一些EVENTS时,vmwatchdog就可以接收到这些EVENTS并执行相应的函数了。



阅读(1119) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~