有一种感动,叫内牛满面,有一种机制,叫模块机制。显然,这种模块机制给那些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点出发,你会发现狗走的是直线,是的,狗都知道,咱还能不知道吗?

Linux内核(6) - 模块机制与“Hello World!的更多相关文章

  1. Linux内核态抢占机制分析(转)

    Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive ...

  2. Linux内核抢占实现机制分析【转】

    Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介 ...

  3. Linux内核中锁机制之RCU、大内核锁

    在上篇博文中笔者分析了关于完成量和互斥量的使用以及一些经典的问题,下面笔者将在本篇博文中重点分析有关RCU机制的相关内容以及介绍目前已被淘汰出内核的大内核锁(BKL).文章的最后对<大话Linu ...

  4. Linux内核中锁机制之完成量、互斥量

    在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内容,首先需明确完成量表示为一个执行单元需要等 ...

  5. Linux内核中锁机制之内存屏障、读写自旋锁及顺序锁

    在上一篇博文中笔者讨论了关于原子操作和自旋锁的相关内容,本篇博文将继续锁机制的讨论,包括内存屏障.读写自旋锁以及顺序锁的相关内容.下面首先讨论内存屏障的相关内容. 三.内存屏障 不知读者是是否记得在笔 ...

  6. Linux内核中锁机制之信号量、读写信号量

    在上一篇博文中笔者分析了关于内存屏障.读写自旋锁以及顺序锁的相关内容,本篇博文将着重讨论有关信号量.读写信号量的内容. 六.信号量 关于信号量的内容,实际上它是与自旋锁类似的概念,只有得到信号量的进程 ...

  7. Linux内核中锁机制之原子操作、自旋锁

    很多人会问这样的问题,Linux内核中提供了各式各样的同步锁机制到底有何作用?追根到底其实是由于操作系统中存在多进程对共享资源的并发访问,从而引起了进程间的竞态.这其中包括了我们所熟知的SMP系统,多 ...

  8. 大话Linux内核中锁机制之RCU、大内核锁

    大话Linux内核中锁机制之RCU.大内核锁 在上篇博文中笔者分析了关于完成量和互斥量的使用以及一些经典的问题,下面笔者将在本篇博文中重点分析有关RCU机制的相关内容以及介绍目前已被淘汰出内核的大内核 ...

  9. 大话Linux内核中锁机制之完成量、互斥量

    大话Linux内核中锁机制之完成量.互斥量 在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内 ...

随机推荐

  1. App优化 Systrace

    简介 trace [tres] vt.跟踪,追踪; 追溯,探索; 探索; 查找; n.痕迹; 痕迹,踪迹; 微量,极少量; 1 1   1 trace [tres] vt.跟踪,追踪; 追溯,探索; ...

  2. 使用ViewDragHelper打造属于自己的DragLayout(抽屉开关 )

    使用ViewDragHelper打造属于自己的DragLayout(抽屉开关 ) DrawLayout这个自己定义的空间非经常见.qq,网易新闻.知乎等等,都有这样的效果,那这样的效果是如何实现的呢? ...

  3. 25个iptables常用示例

    本文将给出25个iptables常用规则示例,这些例子为您提供了些基本的模板,您可以根据特定需求对其进行修改调整以达到期望. 格式 iptables [-t 表名] 选项 [链名] [条件] [-j ...

  4. 【转】php里面也可以使用协程

    原文链接:http://blog.51cto.com/chinalx1/2089327 http://nikic.github.io/2012/12/22/Cooperative-multitaski ...

  5. (排序)快速排序QuickSort

    主要内容: 1.算法思想 2.快速排序算法 3.划分算法partition 4.快排过程图解 5.完整代码 1.算法思想 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一 ...

  6. 栅格计算器函数之Con

    Con函数是condition(条件)的缩写,其作用 语法是: Con(条件,条件为真执行语句,条件为假执行语句[可选]) 或Con(输入栅格,条件为真执行语句,条件为假执行语句[可选],逻辑表达式) ...

  7. Android 之开发积累

    1.后台设置ImageView的src属性 有三种方式:img = (ImageView)this.findViewById(R.id.img_result_analyze); [1]setImage ...

  8. iOS 设置UILabel 的内边距

    iOS 设置UILabel 的内边距 - (void)drawTextInRect:(CGRect)rect { UIEdgeInsets insets = {, , , }; [super draw ...

  9. Electron 入门案例1

    1:package.json 通过npm init生成package.json文件,内容如下: { "name": "t02", "version&q ...

  10. windows XP系统搜索无线网络时提示“windows无法配置此无线连接”,如何处理?

    转自:http://support1.lenovo.com.cn/lenovo/wsi/htmls/detail_12839009034375918.html 文章编号:C191612     201 ...