[置顶] linux内核notifier机制 linux通知链

在linux内核系统中,各个模块、子系统之间是相互独立的。Linux内核可以通过通 知链机制来获取由其它模块或子系统产生的它感兴趣的某些事件。 使用notifier由通知者 可以传递给被通知者长整型参数与指针。在linux中有许多地 方用到,比如reboot通知,cpu调频通知,网卡事件,电池低电警报等等。熟 悉使用notifier有助于linux内核驱动开发。

notifier_block结构:
struct notifier_block {
     int (*notifier_call)(struct notifier_block *, unsigned long, void *);
     struct notifier_block __rcu *next;
     int priority;
};


其中,
1. notifier_call:通知链回调函数,由被通知方提供,第一个  参数notifier_block结构体指针,第二第三个参数分别是由call chain, 也就是通知链发起者传递过来的;
2. notifier_block *next:用于链接成链表的指针;
3. priority:回调函数的优先级,一般默认为0。

何时调用到notifier_call?通常在通知链register与unregister定义文件中就有 notifier call发起函数;


下面是具体应用实例:

被通知文件中:
1:在被通知链文件定义一个notifier call函数:
static int xxxx_notify(struct notifier_block *nb,
         unsigned long status, void *unused)
{
     int rc;

     if (!the_chip) {
         pr_err("not initialized\n");
         return -EINVAL;
     }

     switch (status) {
     case 0:
         pr_debug("0 received\n");
         break;
     case 1:
         pr_debug("1 received\n");

         break;
     case 2:

         break;
     default:
         pr_err("error received\n");
         break;
     }

     return 0;
};



2:定义alarm_notifier通知链,将上面定义的函数入口赋值给函数指针

notifier_call;

static struct notifier_block xxxx_notifier = {
     .notifier_call = xxxx_notify,
};



3:注册alarm_notifier通知链:
probe函数里面:
     {
     -----
     rc = xxxx_register_notifier(&alarm_notifier);
     if (rc) {
         pr_err("unable to register alarm notifier rc=%d\n", rc);
         return rc;
     ------
     }




通知文件中:

1:定义notifier register函数,提供给被通知链调用:
int xxxx_register_notifier(struct notifier_block *nb)
{
     -------
     rc = srcu_notifier_chain_register(&chip->irq_notifier_list, nb);
     -------
     return rc;
}
EXPORT_SYMBOL(xxxx_register_notifier);



2:notifier call发起的地方,这里是在中断的queue work里面调用 
srcu_notifier_call_chain(),其被内核定义在
notifier.c,注意后面的2个参数会传递给回调函数。
static void xxxx_isr_work(struct work_struct *work)
{
     struct xxxx_chip *chip
         = container_of(work, struct xxxx_chip, irq_work);
     int status;

     if (!chip)
         return;

     status = xxxx_status_read();

     srcu_notifier_call_chain(&chip->irq_notifier_list,
                         status, NULL);

}



你可能感兴趣的:(linux通知链)