Linux模块编译

  1. 内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。模块具有以下特点:   
  2. 1 模块本身不被编译入内核映像,从而控制了内核的大小   
  3. 2 模块一旦被加载,它就和内核中的其他部分一样   
  4.     一、 什么是模块   
  5.     模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。   
  6. 首先编写hello.c文件   
  7.     #include<linux/init.h>   
  8.     #include<linux/module.h>   
  9.     //模块许可证声明   
  10.     MODULE_LICENSE("Dual BSD/GPL");   
  11.     //模块加载函数   
  12.     static int hello_init(void)   
  13.     {   
  14.         printk("Imagination is more important than knowledge !/n");   
  15.         return 0;   
  16.     }   
  17.     //模块卸载函数   
  18.     static void hello_exit(void)   
  19.     {   
  20.         printk("hello world exit ! Congratulations!/n");   
  21.     }   
  22.     //这是驱动程序初始化的入口点。对于内置模块,内核在引导时调用该入口  //点;   
  23. 对于可加载模块则在该模块插入内核时才调用。   
  24.   
  25.     module_init(hello_init);   
  26.     //对于可加载模块,内核在此处调用module_cleanup()函数,而对于内置   //的模块,   
  27. 它什么都不做。   
  28.     module_exit(hello_exit);   
  29.     //可选   
  30.     MODULE_AUTHOR("IMAGINECUP");   
  31.     MODULE_DESCRIPTION("A simple Hello World Module");   
  32.     MODULE_ALIAS("A simplest module");   
  33.  编写Makefile文件   
  34.     obj-m           +=hello.o #产生hello模块的目标文件   
  35.     CURRENT_PATH        :=$(shell pwd) #模块所在的当前路径   
  36.     LINUX_KERNEL        :=$(shell uname -r) #Linux内核源代码的当前版本   
  37.     LINUX_KERNEL_PATH   :=/usr/src/linux-headers-$(LINUX_KERNEL) #Linux     内核源代码的绝对路径   
  38.     all:   
  39.         make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #编译模         块   
  40.     clean:   
  41.         make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean #清理   
  42.   
  43. 完成上述两个步骤,然后再模块所在路径运行make命令,即生成模块目标文件(hello.ko)   
  44.   
  45. 然后你可以运行insmod命令来加载模块,当模块加载后你可以通过lsmod查看模块是否被加载进去。rmmod命令用来卸载模块,dmesg命令可以查看模块执行的结果.   
  46.   
  47.   
  48. 知识点:   
  49. 内核符号表:   
  50. 内存地址 符号名 [所属模块]   
  51. 在模块编程中,可以根据符号名从这个文件中检索出其对应的地址,然后直接访问该地址从而获得内核数据。第三列“所属模块”指符号所在的模块名,对于从内核这一母模块移出的符号,这一列为空。   
  52. 可通过/proc/kallsyms查看模块输出的内核符号   
  53.   
  54. 模块依赖   
  55. 如前所述,内核符号表记录了所有模块可以访问的符号及相应的地址。当一个新的模块被装入内核后,它所申明的某些符号就会被登记到这个表中,而这些符号可能被其他模块所引用,这就引出了模块依赖这个问题。   
  56. 一个模块A引用另一个模块B所移出的符号,我们就说模块B被模块A引用,或者说模块A依赖模块B。如果要链接模块A,必须先链接模块B。这种模块间相互依赖的关系就叫模块依赖。   
  57.   
  58. 模块引用计数器   
  59. 为 了确保模块安全地卸载,每个模块都有一个引用计数器。当执行模块所涉及的操作时就递增计数器,在操作结束时就递减这个计数器;另外,当模块B被模块A引用 时,模块B的引用计数就递增,引用结束,计数器递减。什么时候可以卸载这个模块?当然只有这个计数器值为0的时候,例如,当一个文件系统还被安装在系统上 时就不能将其卸载,当这个文件系统不再被使用时,引用计数器就为0,于是可以卸载。

转自:http://imaginecup.javaeye.com/blog/766510

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值