notify机制

notify机制
通知链技术可以概括为:事件的被通知者将事件发生时应该执行的操作通过函数指针方式保存在链表(通知链)中,然后当事件发生时通知者依次执行链表中每一个元素的回调函数完成通知。
一、notify定义

struct notifier_block {
  notifier_fn_t notifier_call;              //回调接口
  struct notifier_block __rcu *next;        //执行完回调接口后的下一个通知结构
  int priority;                             //优先级
};

由宏BLOCKING_NOTIFIER_HEAD来初始化notifier_block链表头

#define BLOCKING_NOTIFIER_HEAD(name)        \
  struct blocking_notifier_head name =      \
    BLOCKING_NOTIFIER_INIT(name)

其注册、注销、通知接口分别为

extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
    struct notifier_block *nb);
extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
    struct notifier_block *nb);
extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
    unsigned long val, void *v);

这几个接口实际上是再封装(针对阻塞,不可阻塞等),通常在不同的内核子系统中,会做不同的封装。注册、注销、通知接口实质原型为:

static int notifier_chain_register(struct notifier_block **nl,
    struct notifier_block *n);
static int notifier_chain_unregister(struct notifier_block **nl,
    struct notifier_block *n);
static int __kprobes notifier_call_chain(struct notifier_block **nl,
          unsigned long val, void *v,int nr_to_call, int *nr_calls);

通常会对这些接口再封装,比如,在FB子系统中,做了如下的封装处理:

static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);    //初始化链表头

/**
 *  fb_register_client - register a client notifier
 *  @nb: notifier block to callback on events
 */
int fb_register_client(struct notifier_block *nb)    //注册notify
{
  return blocking_notifier_chain_register(&fb_notifier_list, nb);
}
EXPORT_SYMBOL(fb_register_client);

/**
 *  fb_unregister_client - unregister a client notifier
 *  @nb: notifier block to callback on events
 */
int fb_unregister_client(struct notifier_block *nb)   //注销notify
{
  return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
}
EXPORT_SYMBOL(fb_unregister_client);

/**
 * fb_notifier_call_chain - notify clients of fb_events
 *
 */
int fb_notifier_call_chain(unsigned long val, void *v)    //通知notify
{
  return blocking_notifier_call_chain(&fb_notifier_list, val, v);
}
EXPORT_SYMBOL_GPL(fb_notifier_call_chain);

注册notify:

fb_register_client()   ---->
      blocking_notifier_chain_register()  ---->
          notifier_chain_register()

注销notify:

fb_unregister_client()  ---->
      blocking_notifier_chain_unregister()  --->
          notifier_chain_unregister()  

通知notify:

fb_notifier_call_chain()  ---->
      blocking_notifier_call_chain()  ---->
          __blocking_notifier_call_chain()  ---->
              notifier_call_chain()

二、示例
例如在RK平台下,编写notify接口的驱动:

static void knock_input_later_resume(void)
{
    DBG("%s :enter\n", __func__);
    gpio_set_value(gpio_info->gpio3,1);


    return;
}

static void knock_input_early_suspend(void)
{
    DBG("%s :enter\n", __func__);


  gpio_set_value(gpio_info->gpio3,0);


    return;
}

static int knock_input_event_notify(struct notifier_block *self,
                       unsigned long action, void *data)  //回调时需要完成的任务,在该事例中是判断不同的FB状态
{

    struct fb_event *event = data;
    int blank_mode = *((int *)event->data);

    switch (blank_mode) {
    case FB_BLANK_UNBLANK:
        knock_input_later_resume();
        break;
    case FB_BLANK_NORMAL:
        knock_input_early_suspend();
        break;
    default:
        knock_input_early_suspend();
        break;
    }

    return 0;
}

static struct notifier_block knock_input_fb_notifier = {
    .notifier_call = knock_input_event_notify,      //回调接口
};


static int xxxx_probe(struct platform_device *pdev){
    .....
    fb_register_client(&knock_input_fb_notifier);    //注册notify
    .....
}

猜你喜欢

转载自blog.csdn.net/u014770862/article/details/72917061