linux消息通知机制,Linux内核通知链(notifier chain)

概述

Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施。为满足这样的需求,内核实现了事件通知链机制(notification chain)。

通知链只能用在各个子系统之间,而不能在内核和用户空间进行事件的通知。组成内核的核心系统代码均位于kernel目录下,通知链表位于kernel/notifier.c中,对应的头文件为include/linux/notifier.h。

事件通知链表是一个事件处理函数的列表,每个通知链都与某个或某些事件有关,当特定的事件发生时,就调用相应的事件通知链中的回调函数,进行相应的处理。

通知链类型

原子通知链

通知链元素的回调函数(当事件发生时要执行的函数)在中断或原子操作上下文中运行,不允许阻塞。对应的链表头结构:

struct atomic_notifier_head {

spinlock_t  lock;

struct  notifier_block *head;

};

可阻塞通知链

通知链元素的回调函数在进程上下文中运行,允许阻塞。对应的链表头:

struct  blocking_notifier_head {

struct  rw_semaphore  rwsem;

struct  notifier_block  *head;

};

原始通知链

对通知链元素的回调函数没有任何限制,所有锁和保护机制都由调用者维护。对应的链表头:

struct  raw_notifier_head {

struct  notifier_block  *head;

};

SRCU通知链

可阻塞通知链的一种变体。对应的链表头:

struct  srcu_notifier_head {

struct  mutex mutex;

struct  srcu_struct  srcu;

struct  notifier_block  *head;

};

相应接口

注册通知链

在通知链表注册时,需要有一个链表头,他指向这个通知链表的第一个元素,这样就可以根据这个链表头找到这个链表中的所有数据。

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)

通知链表

当有事件发生时,就使用notifier_call_chain向某个通知链表发送消息。这个函数会遍历通知链中所有的元素,然后依次调用每一个的回调函数。

static int __kprobes notifier_call_chain(struct notifier_block **nl,

unsigned long val, void *v,

int nr_to_call, int *nr_calls)

实例

#include

#include

#include

#include

#include

static RAW_NOTIFIER_HEAD(test_chain_head);

#define EVENT_A 0x01

#define EVENT_B 0x02

int test_notifier_event(struct notifier_block *nb, unsigned long event, void *v)

{

switch (event) {

case EVENT_A:

printk("test_notifier_event EVENT_A\n");

break;

case EVENT_B:

printk("test_notifier_event EVENT_B\n");

break;

default:

break;

}

return NOTIFY_DONE;

}

static struct notifier_block test_notifier = {

.notifier_call = test_notifier_event,

};

static int __init mynotify_init(void)

{

printk("raw_notifier_chain_register\n");

raw_notifier_chain_register(&test_chain_head, &test_notifier);

printk("raw_notifier_call_chain\n");

raw_notifier_call_chain(&test_chain_head, EVENT_B, NULL);

raw_notifier_call_chain(&test_chain_head, EVENT_A, NULL);

return 0;

}

static void __exit mynotify_exit(void)

{

raw_notifier_chain_unregister(&test_chain_head, &test_notifier);

}

module_init(mynotify_init);

module_exit(mynotify_exit);

MODULE_AUTHOR("lei_wang");

MODULE_LICENSE("GPL");

首先要将notifier_block通过raw_notifier_chain_register注册到notifier_block_head链表上,notifier_block中必须要实现回调函数,然后在需要的时候通过raw_notifier_call_chain去调用notifier_block中的回调函数。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值