前言:Linux内核中的notify通知机制,类似于QT中的事件通知机制,在需要的时刻发送信号,就会引发对应的处理函数执行。Linux内核中的notify提供了核心层,建立通信机制只需使用核心的接口函数实现。对于该机制的实现原理,编写驱动程序不需要过多分析,通过分析,最终这个机制执行过程最终涉及到内嵌汇编代码。
为驱动程序建立一个notify分五步进行:
1、初始化一个notify机制的头(HEAD)
2、实现自定义的注册函数,在函数中调用notify核心层提供的注册接口函数
3、实现自定义的注销函数,在函数中调用notify核心层提供的注销接口函数
4、实现自定义的call_chain函数,在函数中调用notify核心层提供的call_chain接口函数
5、在驱动代码中初始化一个notify项目,完成2、3、4步,在适当的地方调用自定义的call_chain函数
实现的一个例子:
1、exprot_symbols把notify对立为一个模块
#include <linux/notifier.h>
#include <linux/module.h>
static BLOCKING_NOTIFIER_HEAD(pyl_notify);
int pyl_register_notifier(struct notifier_block* nb){
return blocking_notifier_chain_register(&pyl_notify,nb);
}
EXPORT_SYMBOL(pyl_register_notifier);
int pyl_unregister_notifier(struct notifier_block* nb){
return blocking_notifier_chain_unregister(&pyl_notify,nb);
}
EXPORT_SYMBOL(pyl_unregister_notifier);
/*
val:参数
v:数据指针
*/
int pyl_notifier_call_chain(unsigned long val, void *v){
return blocking_notifier_call_chain(&pyl_notify,val,v);
}
EXPORT_SYMBOL(pyl_notifier_call_chain);
MODULE_LICENSE("GPL");
2、调用export_symbols导出的函数符号,不过要在文件中声明一下。
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
int pyl_register_notifier(struct notifier_block* nb);
int pyl_unregister_notifier(struct notifier_block* nb);
int pyl_notifier_call_chain(unsigned long val, void *v);
struct class* pyl_class;
typedef struct pyl2019{
struct cdev* pyl_dev;
dev_t pyl_t;
struct semaphore pyl_sem;//原子操作
}pyl_chrdev;
pyl_chrdev* pyl_c=NULL;
static int for_pyl_notify_callBack(struct notifier_block *nb, unsigned long val, void *v){
printk(KERN_INFO"\n i am a notifier \n");
return 0;
}
static struct notifier_block pyl_notify={
.notifier_call=for_pyl_notify_callBack,
};
int notify_open(struct inode *node, struct file *fil){
pyl_notifier_call_chain(0,NULL);
return 0;
}
int notify_release(struct inode *node, struct file *fil){
int ret;
ret=pyl_unregister_notifier(&pyl_notify);
return ret;
}
static struct file_operations pyl_fops={
.owner=THIS_MODULE,
.open=notify_open,
.release=notify_release,
};
static int __init pyl_init(void){
int ret;
pyl_c=(pyl_chrdev*)kmalloc(sizeof(pyl_chrdev),GFP_KERNEL);
if(!pyl_c){
goto kmalloc_err;
}
sema_init(&pyl_c->pyl_sem,1);
ret=alloc_chrdev_region(&pyl_c->pyl_t,0,1,"pyl");
pyl_c->pyl_dev = cdev_alloc();
if(!pyl_c->pyl_dev){
goto alloc_err;
}
cdev_init(pyl_c->pyl_dev,&pyl_fops);
ret=cdev_add(pyl_c->pyl_dev,pyl_c->pyl_t, 1);
if(ret<0){
goto err;
}
pyl_class = class_create(THIS_MODULE, "pyl");
device_create(pyl_class,NULL,MKDEV(pyl_c->pyl_t,0), NULL, "pyloooooo");
printk(KERN_DEBUG"init OK \n");
pyl_register_notifier(&pyl_notify);
return 0;
err:
cdev_del(pyl_c->pyl_dev);
alloc_err:
unregister_chrdev_region(pyl_c->pyl_t,1);
kfree(pyl_c);
kmalloc_err:
return -1;
}
static void __exit pyl_exit(void){
cdev_del(pyl_c->pyl_dev);
unregister_chrdev_region(pyl_c->pyl_t,1);
device_destroy(pyl_class,MKDEV(pyl_c->pyl_t,0));
class_destroy(pyl_class);
kfree(pyl_c);
}
MODULE_LICENSE("GPL");
module_init(pyl_init);
module_exit(pyl_exit);
上面的驱动代码的功能是,在初始化函数中注册一个通知链,在应用程序打开该设备驱动程序时,就发送notifier信号,执行call_chain回调函数。在1中可以看到有相关函数。