设为首页 收藏本站
查看: 279|回复: 0

[经验分享] Linux 内核通知链随笔【下】

[复制链接]
累计签到:77 天
连续签到:1 天
发表于 2014-8-14 09:10:50 | 显示全部楼层 |阅读模式
书接上回,闲话不表。话说,女神无论是在土豪或者屌丝那里都找不到归属感,冥冥之中天上掉下来一个王子(PS:又名高富帅),既可以满足女神的物质需求还可以满足女神的精神需求:



    /*GFS.c*/
    #include <asm/uaccess.h>
    #include <linux/types.h>
    #include <linux/kernel.h>
    #include <linux/sched.h>
    #include <linux/notifier.h>
    #include <linux/init.h>
    #include <linux/types.h>
    #include <linux/module.h>
    MODULE_LICENSE("GPL");

    /*
    * 注册通知链
    */

    extern int register_godness_notifier(struct notifier_block*);
    extern int unregister_godness_notifier(struct notifier_block*);

    static int sweet_heart_requirments(struct notifier_block *this, unsigned long event, void *ptr)
    {
            switch(event)
            {
                    case 0:
                            printk("[GFS]Hi honey,the VISA card is ready for you! \n");
                            break;
                    case 1:
                            printk("[GFS]Hi honey,let me play the piano for you! \n");
                            break;
                    default:
                            break;
            }
            return 0;
    }

    static struct notifier_block honey_notifier =
    {
            .notifier_call = sweet_heart_requirments,
            .priority = 2,
    };

    static int __init GFS_register(void)
    {
            int err;
            printk("[GFS]GFS register honey_requirment response to Godness...");

            err = register_godness_notifier(&honey_notifier);
            if (err)
            {
                    printk("Refused!\n");
                    return -1;
            }
            printk("Accepted!\n");

            return err;
    }

    /*
    * 卸载刚刚注册了的通知链
    */
    static void __exit GFS_unregister(void)
    {
            unregister_godness_notifier(&honey_notifier);
            printk("[GFS]GFS broke up with Godness!(How sadness)\n");
    }
    module_init(GFS_register);
    module_exit(GFS_unregister);


   然后重新上演前面的故事,播放的指令如下:
[iyunv@localhost test]# insmod Goddess.ko;sleep 4;insmod Tuhao.ko; sleep 4; insmod Diors.ko;sleep 4; insmod GFS.ko
[iyunv@localhost test]# rmmod GFS.ko;rmmod Diors.ko;rmmod Tuhao.ko;rmmod Goddess.ko
[iyunv@localhost test]#

   播放内容如下:
Jun  2 00:39:41 localhost kernel: [Attention]The Godness coming into the world!
Jun  2 00:39:41 localhost kernel: [Godness]requirements thread starting...
Jun  2 00:39:44 localhost kernel: [Godness]requirment type: 1
Jun  2 00:39:45 localhost kernel: [Tuhao]Tuhao register Cash event  to Godness...Accepted!
Jun  2 00:39:47 localhost kernel: [Godness]requirment type: 0
Jun  2 00:39:47 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:39:49 localhost kernel: [Diors]Diors register music_requirment response to Godness...Accepted!
Jun  2 00:39:50 localhost kernel: [Godness]requirment type: 1
Jun  2 00:39:50 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:39:53 localhost kernel: [Godness]requirment type: 1
Jun  2 00:39:53 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:39:53 localhost kernel: [GFS]GFS register honey_requirment response to Godness...Accepted!
Jun  2 00:39:56 localhost kernel: [Godness]requirment type: 1
Jun  2 00:39:56 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:39:56 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:39:59 localhost kernel: [Godness]requirment type: 0
Jun  2 00:39:59 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:39:59 localhost kernel: [GFS]Hi honey,the VISA card is ready for you!
Jun  2 00:40:02 localhost kernel: [Godness]requirment type: 1
Jun  2 00:40:02 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:40:02 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:40:05 localhost kernel: [Godness]requirment type: 1
Jun  2 00:40:05 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:40:05 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:40:08 localhost kernel: [Godness]requirment type: 0
Jun  2 00:40:08 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:40:08 localhost kernel: [GFS]Hi honey,the VISA card is ready for you!
Jun  2 00:40:11 localhost kernel: [Godness]requirment type: 1
Jun  2 00:40:11 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:40:11 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:40:11 localhost kernel: [Godness]requirements thread ended!
Jun  2 00:40:52 localhost kernel: [GFS]GFS broke up with Godness!(How sadness)
Jun  2 00:40:52 localhost kernel: [Diors]Tuhao is giving up Godness!(What a pity)
Jun  2 00:40:52 localhost kernel: [Tuhao]Tuhao is giving up Godness!(Son of bitch)
Jun  2 00:40:52 localhost kernel: [Attention] The Godness leaving out!

   我们可以看到,高富帅向女神需求通知链上注册的回调函数,优先级也是2,我们在测试的时候是先加载土豪、再加载屌丝最后加载高富帅,所以每当女神提出需求时,如果是金钱需求则最先被土豪响应,如果是精神需求则最先被屌丝给响应了。这完全不符合高富帅的特征啊,于是高富帅将自己的优先级提高到5,然后replay一次:



    static struct notifier_block honey_notifier =
    {
            .notifier_call = sweet_heart_requirments,
            .priority = 5,
    };


    结果如下:
Jun  2 00:50:29 localhost kernel: [Attention]The Godness coming into the world!
Jun  2 00:50:29 localhost kernel: [Godness]requirements thread starting...
Jun  2 00:50:32 localhost kernel: [Godness]requirment type: 0
Jun  2 00:50:33 localhost kernel: [Tuhao]Tuhao register Cash event  to Godness...Accepted!
Jun  2 00:50:35 localhost kernel: [Godness]requirment type: 0
Jun  2 00:50:35 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:50:37 localhost kernel: [Diors]Diors register music_requirment response to Godness...Accepted!
Jun  2 00:50:38 localhost kernel: [Godness]requirment type: 1
Jun  2 00:50:38 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:50:41 localhost kernel: [Godness]requirment type: 0
Jun  2 00:50:41 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:50:41 localhost kernel: [GFS]GFS register honey_requirment response to Godness...Accepted!
Jun  2 00:50:44 localhost kernel: [Godness]requirment type: 0
Jun  2 00:50:44 localhost kernel: [GFS]Hi honey,the VISA card is ready for you!
Jun  2 00:50:44 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:50:47 localhost kernel: [Godness]requirment type: 1
Jun  2 00:50:47 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:50:47 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:50:50 localhost kernel: [Godness]requirment type: 1
Jun  2 00:50:50 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:50:50 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:50:53 localhost kernel: [Godness]requirment type: 0
Jun  2 00:50:53 localhost kernel: [GFS]Hi honey,the VISA card is ready for you!
Jun  2 00:50:53 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:50:56 localhost kernel: [Godness]requirment type: 0
Jun  2 00:50:56 localhost kernel: [GFS]Hi honey,the VISA card is ready for you!
Jun  2 00:50:56 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:50:59 localhost kernel: [Godness]requirment type: 1
Jun  2 00:50:59 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:50:59 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:50:59 localhost kernel: [Godness]requirements thread ended!
Jun  2 00:51:04 localhost kernel: [GFS]GFS broke up with Godness!(How sadness)
Jun  2 00:51:04 localhost kernel: [Diors]Tuhao is giving up Godness!(What a pity)
Jun  2 00:51:04 localhost kernel: [Tuhao]Tuhao is giving up Godness!(Son of bitch)
Jun  2 00:51:04 localhost kernel: [Attention] The Godness leaving out!

    这次我们看到,高富帅终于如愿以偿地于第一时间响应到了女神的需求。再考虑一种情况,如果高富帅不想让女神的需求传递到土豪和屌丝那里,怎么办?其实也很简单,高富帅只要在自己的响应函数里向女神返回NOTIFY_STOP值就可以了:



    static int sweet_heart_requirments(struct notifier_block *this, unsigned long event, void *ptr)
    {
            switch(event)
            {
                    case 0:
                            printk("[GFS]Hi honey,the VISA card is ready for you! \n");
                            break;
                    case 1:
                            printk("[GFS]Hi honey,let me play the piano for you! \n");
                            break;
                    default:
                            break;
            }
            return NOTIFY_STOP;
    }


   然后故事就变成酱紫了:
Jun  2 00:55:56 localhost kernel: [Attention]The Godness coming into the world!
Jun  2 00:55:56 localhost kernel: [Godness]requirements thread starting...
Jun  2 00:55:59 localhost kernel: [Godness]requirment type: 1
Jun  2 00:56:00 localhost kernel: [Tuhao]Tuhao register Cash event  to Godness...Accepted!
Jun  2 00:56:02 localhost kernel: [Godness]requirment type: 0
Jun  2 00:56:02 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:56:04 localhost kernel: [Diors]Diors register music_requirment response to Godness...Accepted!
Jun  2 00:56:05 localhost kernel: [Godness]requirment type: 1
Jun  2 00:56:05 localhost kernel: [Diors]Hi girl,This is a classic Music disk,take it.
Jun  2 00:56:08 localhost kernel: [Godness]requirment type: 0
Jun  2 00:56:08 localhost kernel: [Tuhao]Hi Baby,$$$$$$$$ 么么哒
Jun  2 00:56:08 localhost kernel: [GFS]GFS register honey_requirment response to Godness...Accepted!
Jun  2 00:56:11 localhost kernel: [Godness]requirment type: 1
Jun  2 00:56:11 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:56:14 localhost kernel: [Godness]requirment type: 0
Jun  2 00:56:14 localhost kernel: [GFS]Hi honey,the VISA card is ready for you!
Jun  2 00:56:17 localhost kernel: [Godness]requirment type: 1
Jun  2 00:56:17 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:56:20 localhost kernel: [Godness]requirment type: 1
Jun  2 00:56:20 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:56:23 localhost kernel: [Godness]requirment type: 0
Jun  2 00:56:23 localhost kernel: [GFS]Hi honey,the VISA card is ready for you!
Jun  2 00:56:26 localhost kernel: [Godness]requirment type: 1
Jun  2 00:56:26 localhost kernel: [GFS]Hi honey,let me play the piano for you!
Jun  2 00:56:26 localhost kernel: [Godness]requirements thread ended!
Jun  2 00:56:30 localhost kernel: [GFS]GFS broke up with Godness!(How sadness)
Jun  2 00:56:30 localhost kernel: [Diors]Tuhao is giving up Godness!(What a pity)
Jun  2 00:56:30 localhost kernel: [Tuhao]Tuhao is giving up Godness!(Son of bitch)
Jun  2 00:56:30 localhost kernel: [Attention] The Godness leaving out!

   在高富帅还没将自己的响应函数注册到女神之前,女神的物质需求是被土豪给霸占了,精神需求被屌丝给享有了,等到00:56:08秒之后,高富帅的请求被女神接受了,于是接下来就没土豪和屌丝啥事儿了。OK,到这里我们的故事也就讲完了,让我们回头来总结一下Linux内核中通知链的相关知识点(首先非常感谢wwx0715兄弟指出了我【上】篇博文的一个错误,在【上】篇博文里我将通知链的优先级弄反了,是数字越大优先级越高,通知函数越是先会被执行,在此非常感谢。):
   1、如果一个子系统A在运行过程中会产生一个实时的事件,而这些事件对其他子系统来说非常重要,那么系统A可以定义一个自己的通知链对象,根据需求可以选择原子通知链、非阻塞通知链或者原始通知链,并向外提供向这个通知链里注册、卸载执行事件的回调函数的接口;
   2、如果子系统B对子系统A中的某(些)个事件感兴趣,或者说强依赖,就是说系统B需要根据系统A中某些事件来执行自己特定的操作,那么此时系统就需要实例化一个通知块struct notifier_block XXX{},然后编写通知块里的回调处理函数来响应A系统中响应的事件就可以了;
   3、在我们这个示例里用到了struct notifier_block{}的优先级特性,其实在标准内核里每个实例化的通知块都没有用优先级字段。不用优先级字段的结果就是,先注册的通知块里的回调函数在事件发生时会先执行。注意这里所说的后注册指的是模块被动态加载内核的先后顺序,和哪个模块的代码先写完没有关系,注意区分。意思就是说,如果子系统B和C都对子系统A的up事件感兴趣,B和C在向A注册up事件的回调函数时并没有指定函数的优先级。无论是通过insmod手动加载模块B和C,还是系统boot时自动加载B和C,哪个模块先被加载,它的回调函数在A系统的up事件发生时会先被执行;
   4、关于通知链的回调函数,正常情况下都需要返回NOTIFY_OK或者NOTIFY_DONE,这样通知链上后面挂载的其他函数可以继续执行。如果返回NOTIFY_STOP,则会使得本通知链上后续挂载的函数无法得到执行,除非你特别想这么做,否则在编写通知链的回调函数时一般最好不要返回这个值;
   5、通知链上回调函数的原型int (*notifier_call)(struct notifier_block *, unsigned long, void *),其中第二个参数一般用于指明事件的类型,通常都是一个整数。而第三个参数是一个void类型的内存地址,在不同的子系统中用于表示不同的信息,例如在邻居子系统里,第三个参数可以是一个邻居信息结构体对象的地址struct neighbour *v;而在驱动框架里又可以是一个net_device{}结构体对象的地址等等;我们在设计自己的通知链系统可以用第三个入参实现在通知系统与被通知系统之间实现数据的传递,以便被通知系统的工作可以更加紧凑、高效;
   6、如果以后再看到内核中某个子系统在调用通知链的注册函数时,不要心虚、不要怕。做到以下两点就没事儿了:
       第一:心里首先要明确,这个注册通知链回调函数的系统一定和提供通知链的系统有某种连续,且本系统需要对那个系统的某些重要事件进行响应;
       第二:看本系统注册的通知回调函数的实现,具体看它对那些事件感兴趣,并且是怎么处理的;
       第三:看看原提供通知链对象的系统有哪些事件;
   最后,心里也就明白了这个系统为什么要用通知链来感知别的系统的变化了,这样一来,对这两个系统从宏观到甚微观的层面就都有一个总体的认识和把握,后续再研究起来就顺风顺水了,而这也正是内核通知链的神奇所在。
   完。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-23744-1-1.html 上篇帖子: Linux 内核通知链随笔【中】 下篇帖子: UNIX网络编程--进程间通信与套接字平台搭建
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表