zoukankan      html  css  js  c++  java
  • Linux内核(6)

    有一种感动,叫内牛满面,有一种机制,叫模块机制。显然,这种模块机制给那些Linux的发烧友们带来了方便,因为模块机制意味着人们可以把庞大的Linux内核划分为许许多多个小的模块。对于编写设备驱动程序的开发者来说,从此以后他们可以编写设备驱动程序却不需要把她编译进内核,不用reboot机器,她只是一个模块,当你需要她的时候,你可以把她抱入怀中(insmod),当你不再需要她的时候,你可以把她一脚踢开(rmmod)。 

    于是,忽如一夜春风来,内核处处是模块。让我们从一个伟大的例子去认识模块。这就是传说中的"Hello World!",这个梦幻般的名字我们看过无数次了,每一次她出现在眼前,就意味着我们开始接触一种新的计算机语言了。(某程序员对书法十分感兴趣,退休后决定在这方面有所建树。于是花重金购买了上等的文房四宝。一日,饭后突生雅兴,一番磨墨拟纸,并点上了上好的檀香,颇有王羲之风范,又具颜真卿气势,定神片刻,泼墨挥毫,郑重地写下一行字:hello world) 

    请看下面这段代码,她就是Linux下的一个最简单的模块。当你安装这个模块的时候,她会用她特有的语言向你表白:“Hello,world!”,而后来你卸载了这个模块,你无情抛弃了她,她很伤心,她很绝望,但她没有抱怨,她只是淡淡地说,“Goodbye,cruel world!”(再见,残酷的世界!)

    /************ hello.c *********************/

         1 #include <linux/init.h>  /* Needed for the macros */
      2 #include <linux/module.h> /* Needed for all modules */
      3 MODULE_LICENSE("Dual BSD/GPL");
      4 MODULE_AUTHOR("fudan_abc");
      5
      6 static int __init hello_init(void)
      7 {
      8         printk(KERN_ALERT "Hello, world!/n");
        9         return 0;
       10 }
      11
       12 static void __exit hello_exit(void)
        13 {
       14         printk(KERN_ALERT "Goodbye, cruel world/n");
        15 }
       16
        17 module_init(hello_init);
        18 module_exit(hello_exit);  

    你需要使用module_init()和module_exit(),你可以称它们为函数,不过实际上它们是一些宏,你可以不用去知道她们背后的故事,只需要知道,在Linux Kernel 2.6的世界里,你写的任何一个模块都需要使用它们来初始化或退出,或者说注册以及后来的注销。 

    当你用module_init()为一个模块注册了之后,在你使用insmod这个命令去安装的时候,module_init()注册的函数将会被执行。而当你用rmmod这个命令去卸载一个模块的时候,module_exit()注册的函数将会被执行。module_init()被称为驱动程序的初始化入口(driver initialization entry point)。 

    怎么样演示以上代码的运行呢?没错,你需要一个Makefile。

    1 # To build modules outside of the kernel tree, we run "make"
       2 # in the kernel source tree; the Makefile these then includes this
       3 # Makefile once again.
        4 # This conditional selects whether we are being included from the
        5 # kernel Makefile or not.
        6 ifeq ($(KERNELRELEASE),)
       7
        8     # Assume the source tree is where the running kernel was built
        9     # You should set KERNELDIR in the environment if it's elsewhere
        10     KERNELDIR ?= /lib/modules/$(shell uname -r)/build
       11     # The current directory is passed to sub-makes as argument
       12     PWD := $(shell pwd)
        13
        14 modules:
        15         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
        16
        17 modules_install:
        18         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
        19
        20 clean:
        21         rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
        22
        23 .PHONY: modules modules_install clean
        24
        25 else
        26     # called from kernel build system: just declare what our modules are
        27     obj-m := hello.o
        28 endif  

    在lwn.net上可以找到这个例子,你可以把以上两个文件放在你的某个目录下,然后执行make,也许你不一定能成功,因为Linux Kernel 2.6要求你编译模块之前,必须先在内核源代码目录下执行make,换言之,你必须先配置过内核,执行过make,然后才能make你自己的模块。原因就不细说了,你按着要求的这么去做就行了。在内核顶层目录make过之后,你就可以在你当前放置Makefile的目录下执行make了。make之后你就应该看到一个叫做hello.ko的文件生成了,恭喜你,这就是你将要测试的模块。

    执行命令,

    #insmod hello.ko  

    同时在另一个窗口,用命令tail -f /var/log/messages察看日志文件,你会看到Hello world被打印了出来。再执行命令,

    #rmmod hello.ko  

    此时,在另一窗口你会看到Goodbye,cruel world!被打印了出来。 

    到这里,我该恭喜你,因为你已经能够编写Linux内核模块了。这种感觉很美妙,不是吗?你可以嘲笑秦皇汉武略输文采唐宗宋祖稍逊风骚,还可以嘲笑一代天骄成吉思汗只识弯弓射大雕了。是的,阿娇姐姐告诉我们,只要我喜欢,还有什么不可以。 

           日后我们会看到,2.6内核中,每个模块都是以module_init开始,以module_exit结束。对大多数人来说没有必要知道这是为什么,记住就可以了,对大多数人来说,这就像是1+1为什么等于2一样,就像是两点之间最短的是直线,不需要证明,如果一定要证明两点之间直线最短,可以扔一块骨头在B点,让一条狗从A点出发,你会发现狗走的是直线,是的,狗都知道,咱还能不知道吗?

  • 相关阅读:
    selenium webdriver简介
    web自动化selenium环境搭建
    web自动化基础之web页面组成
    接口测试基础八--接口自动化前期准备
    小程序测试关注点之一-登录授权
    python实现十大经典算法
    pytest 框架之pytest-html报告生成
    pytest 框架与 unittest 框架的对比
    selenium _上传操作
    selenium 常见操作,使用 js 操作-日期框及文本框
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8448795.html
Copyright © 2011-2022 走看看