# linux观察者模式 **Repository Path**: design_pattern_lwq/linux_observer_mode ## Basic Information - **Project Name**: linux观察者模式 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-05-19 - **Last Updated**: 2021-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README Linux虽然是面向过程的c语言写成的,但是却可以表达面向对象的思想。 在linux中,如果你想让自己的行为被别人注意到,那么你就要申请一条通知链,然后让所有关注你自己的实体注册到这条通知链上,最终的效果就是一旦发生一件值得关注的事情,所有的注册者都可以得到通知,想得到通知的实体注册代码如下: ``` int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *n) { unsigned long flags; int ret; spin_lock_irqsave(&nh->lock, flags); ret = notifier_chain_register(&nh->head, n); spin_unlock_irqrestore(&nh->lock, flags); return ret; } ``` ``` static int notifier_chain_register(struct notifier_block **nl, struct notifier_block *n) { while ((*nl) != NULL) { if (n->priority > (*nl)->priority) break; nl = &((*nl)->next); } n->next = *nl; rcu_assign_pointer(*nl, n); return 0; } ``` 以上的代码中atomic_notifier_chain_register的参数nh就是希望别人关注的实体申请的一条通知链,而参数n就是关注的实体注册的一个结构,该结构体包含了一个回调函数,一旦通知来临,该回调函数被调用。c语言中的回调函数其实和OO中的抽象类和接口中的抽象方法的意义是一样的,本质上就是一个接口,只是告诉调用方你只管调用就可以了,不必知道它的实现以及是否已经被实现,也不用管它到底做了哪些事,在观察者模式中,实际上解耦了通知者和被通知者,因此应用观察者模式可以得到两个好处,第一可以轻松实现框架的层次感,做到各司其职,第二就是可以合理安排对所在的层次,一个对象没有必要什么都管,这其实不是两个好处,而是一个好处的两个方面。这样我就可以独立的更改通知者的通知方式和被通知者得到通知的时候的反映方式。对于linux而言,主动通知的代码是以下: ``` int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls) { int ret; rcu_read_lock(); ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); rcu_read_unlock(); return ret; } static int __kprobes notifier_call_chain(struct notifier_block **nl, unsigned long val, void *v, int nr_to_call, int *nr_calls) { int ret = NOTIFY_DONE; struct notifier_block *nb, *next_nb; nb = rcu_dereference(*nl); while (nb && nr_to_call) { next_nb = rcu_dereference(nb->next); ret = nb->notifier_call(nb, val, v); //调用观察者注册是回调函数 if (nr_calls) (*nr_calls)++; if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) break; nb = next_nb; nr_to_call--; } return ret; } ``` 所有的观察者继承于同一个抽象的观察者类,然后被观察者发出通知时就可以统一调用观察者抽象类对象的抽象接口了。从代码实现上看,更加简洁了,抽象类虽然没有,但是仍然不妨碍c语言组织子类,就是用一个链表,其实就是通知链,于是通知者根本不用管别的只需要调用一个函数就可以了,连什么抽象接口都不用调用,只要调用一个atomic_notifier_call_chain,并且知道通知链就可以了。