Linux 文件通知机制,linux系统通知机制

1. 基本机制

1)数据结构

struct notifier_block

{

int (*notifier_call)(struct notifier_block *self, unsigned long, void *);

struct notifier_block *next;

int priority; /*用于对注册者进行优先级排队,高优先级的处理例程将被优先执行,由注册者自己指定 */

};

2)基本例程

extern int notifier_chain_register(struct notifier_block **list, struct notifier_block *n);

说明:注册到某个notifier_block链;这时的n可以只要初始化(*notifier_call)指针;

extern int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n);

说明:从某个notifier_block链中移去n;

extern int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v);

说明:轮循执行某个notifier_block链中的所有notifier_block,对其(*notifier_call)传入参数val和*v;

其中val应该是EVENT NUMBER,而*v是导致这个事件的数据结构,比如某个网络设备UP,则val=NETDEV_UP,v=dev;

3)返回值

#define NOTIFY_DONE 0x0000 /* Don't care */

#define NOTIFY_OK 0x0001 /* Suits me */

#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */

#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */

4)已定义事件

/*

* Declared notifiers so far. I can imagine quite a few more chains

* over time (eg laptop power reset chains, reboot chain (to clean

* device units up), device [un]mount chain, module load/unload chain,

* low memory chain, screenblank chain (for plug in modular screenblankers)

* VC switch chains (for loadable kernel svgalib VC switch helpers) etc...

*/

/* netdevice notifier chain */

#define NETDEV_UP 0x0001 /* For now you can't veto a device up/down */

#define NETDEV_DOWN 0x0002

#define NETDEV_REBOOT 0x0003 /* Tell a protocol stack a network interface

detected a hardware crash and restarted

- we can use this eg to kick tcp sessions

once done */

#define NETDEV_CHANGE 0x0004 /* Notify device state change */

#define NETDEV_REGISTER 0x0005

#define NETDEV_UNREGISTER 0x0006

#define NETDEV_CHANGEMTU 0x0007

#define NETDEV_CHANGEADDR 0x0008

#define NETDEV_GOING_DOWN 0x0009

#define NETDEV_CHANGENAME 0x000A

#define SYS_DOWN 0x0001 /* Notify of system down */

#define SYS_RESTART SYS_DOWN

#define SYS_HALT 0x0002 /* Notify of system halt */

#define SYS_POWER_OFF 0x0003 /* Notify of system power off */

2. 举例分析

以网络设备的通知信息块netdev_chain为例来说明如何使用notification机制。

在net/core/dev.c中定义了netdev_chain链:

static struct notifier_block *netdev_chain=NULL;

提供别的模块的接口,以便它们使用netdev_chain链:

/*

* Device change register/unregister. These are not inline or static

* as we export them to the world.

*/

/**

* register_netdevice_notifier - register a network notifier block

* @nb: notifier

*

* Register a notifier to be called when network device events occur.

* The notifier passed is linked into the kernel structures and must

* not be reused until it has been unregistered. A negative errno code

* is returned on a failure.

*/

int register_netdevice_notifier(struct notifier_block *nb)

{

return notifier_chain_register(&netdev_chain, nb);

}

/**

* unregister_netdevice_notifier - unregister a network notifier block

* @nb: notifier

*

* Unregister a notifier previously registered by

* register_netdevice_notifier(). The notifier is unlinked into the

* kernel structures and may then be reused. A negative errno code

* is returned on a failure.

*/

int unregister_netdevice_notifier(struct notifier_block *nb)

{

return notifier_chain_unregister(&netdev_chain,nb);

}

以X25为例来说明使用者(--前面所说的订阅者)。

在af_x25.c中,定义了:

struct notifier_block x25_dev_notifier = {

notifier_call: x25_device_event,

};

然后模块初始化时向netdev_chain注册:

static int __init x25_init(void)

{

... ...

register_netdevice_notifier(&x25_dev_notifier);

... ...

}

比如当NETDEV_UP事件发生时(--前面所说的事件发布者网卡驱动--》调用dev.c),调用到:

notifier_call_chain(&netdev_chain, NETDEV_UP, dev);

就会执行到x25_dev_notifier中注册的处理例程:x25_device_event,至于对相应的事件(event number)是不是感兴趣,

需要处理例程自己来判断。

static int x25_device_event(struct notifier_block *this, unsigned long event, void *ptr)

{

struct net_device *dev = (struct net_device *)ptr;

struct x25_neigh *neigh;

if (dev->type == ARPHRD_X25

#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)

|| dev->type == ARPHRD_ETHER

#endif

) {

switch (event) {

case NETDEV_UP:

x25_link_device_up(dev);

break;

case NETDEV_GOING_DOWN:

if ((neigh = x25_get_neigh(dev)))

x25_terminate_link(neigh);

break;

case NETDEV_DOWN:

x25_kill_by_device(dev);

x25_route_device_down(dev);

x25_link_device_down(dev);

break;

}

}

return NOTIFY_DONE;

}

所有关于网络设备的事件全部在net/core/dev.c中发生,从而引发notifier_call_chain(&netdev_chain,val, dev)的调用:

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_UP, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);

Dev.c (linux\net\core): notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);

3. 总结

从上面的分析可以看出,Linux下的Notification机制不是通过消息的方式实现的,而是一旦外部事件发生,所以对这个事件感兴趣的模块都会立即响应这个事件。但是,这个通知机制的效率不是很高,因为它的粒度不够细,比如A对E1、E2事件感兴趣,B对E2、E3感兴趣,但是E1~E3都是由N链来管理的,这样当发生E1事件时,A、B的处理例程都会被调用一次。如果能够区分对待不同模块感兴趣的事件集,然后只把事件发送到感兴趣的模块,效率会更高一些。另外,对优先级的处理是必须得,但是如何利用这个优先级似乎没有很好的说明和例证。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值