内核模块学习--编译自己的第一个内核模块hello_module

原创 2012年03月29日 20:38:14

1,下载源码
xin@xin-desktop:~$  sudo apt-get source linux-image-2.6.32-38-generic
最终安装在目录:/usr/src/linux-2.6.32/
2,编写源码hello_module.c和Makefile
(1)新建一个目录mytest
xin@xin-desktop:~/mytest$ vi hello_module.c
    #include <linux/init.h>         /* printk() */
    #include <linux/module.h>       /* __init __exit */

    static int  __init  hello_init(void)      /*模块加载函数,通过insmod命令加载模块时,被自动执行*/
    {
      printk(KERN_INFO " Hello World enter\n");
      return 0;
    }
    static void  __exit  hello_exit(void)    /*模块卸载函数,当通过rmmod命令卸载时,会被自动执行*/
    {
      printk(KERN_INFO " Hello World exit\n ");
    }

    module_init(hello_init);
    module_exit(hello_exit);

    MODULE_AUTHOR("xin");           /*模块作者,可选*/
    MODULE_LICENSE("Dual BSD/GPL");     /*模块许可证明,描述内核模块的许可权限,必须*/
    MODULE_DESCRIPTION("A simple Hello World Module"); /*模块说明,可选*/

(2)写一个Makefile文件:
内容如下:
#目标文件
obj-m :=hello_module.o

#当模块有多个文件组成时,添加本句
#module-objs := file1.o file.o  

#内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路>径      
KDIR :=/usr/src/linux-2.6.32/

#模块源文件路径             
PWD := $(shell pwd)

all:      
        $(MAKE)  -C  $(KDIR)  SUBDIRS=$(PWD)  modules  
        @rm -rf *.mod.*  
        @rm -rf .*.cmd  
        @rm -rf *.o  
        @rm -rf Module.*  
clean:  
        rm -rf *.ko

 
3,编译
xin@xin-desktop:~/mytest$  make
make: Entering directory `/usr/src/linux-2.6.32'

  ERROR: Kernel configuration is invalid.
         include/linux/autoconf.h or include/config/auto.conf are missing.
         Run 'make oldconfig && make prepare' on kernel src to fix it.


  WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
           is missing; modules will have no dependencies and modversions.

  ........................................
  ........................................

解决方法:
xin@xin-desktop:/usr/src/linux-2.6.32$ sudo make oldconfig
xin@xin-desktop:/usr/src/linux-2.6.32$ sudo make prepare

再次编译:
xin@xin-desktop:~/mytest$ make
还是有错:
make: Entering directory `/usr/src/linux-2.6.32'

 
WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
           is missing; modules will have no dependencies and modversions.

  CC [M]  /home/xin/mytest/hello_module.o
  Building modules, stage 2.
  MODPOST 1 modules
/bin/sh: scripts/mod/modpost: not found
make[1]: *** [__modpost] 错误 127
make: *** [modules] 错误 2
make: Leaving directory `/usr/src/linux-2.6.32'

看到提示说没有scripts/mod/modpost,那我们就编译它
xin@xin-desktop:/usr/src/linux-2.6.32$ make scripts
  HOSTCC  scripts/genksyms/genksyms.o
  SHIPPED scripts/genksyms/lex.c
  SHIPPED scripts/genksyms/parse.h
  SHIPPED scripts/genksyms/keywords.c
  HOSTCC  scripts/genksyms/lex.o
  SHIPPED scripts/genksyms/parse.c
 HOSTCC  scripts/genksyms/parse.o
  HOSTLD  scripts/genksyms/genksyms
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/modpost.o
  HOSTCC  scripts/mod/sumversion.o
 
HOSTLD  scripts/mod/modpost
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/conmakehash

OK,好了

再来解决这一个warning(前面没有关注,后面发现这个还是致命的):
 WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
           is missing; modules will have no dependencies and modversions.

原因:通常头核心包中是没有
Module.symvers这个文件的,要想获取这个文件只能到下载相同版本核心的头文件,是下载不是
apt-get install  !!!,只有下载的头文件中才有这个Module.symvers。把Module.symvers 复制到核心包中。
然后重新编译驱动:xin@xin-desktop:~/mytest$ make
将解决这个warning,同时也解决了版本不正确的问题。
(我不知道有多少人会碰上这样的问题,反正google中我发现没有人能说明白这个问题)

4,加载模块
xin@xin-desktop:~/mytest$ ls
hello_module.c   modules.order   hello_module.ko  Makefile  
xin@xin-desktop:~/mytest$ sudo insmod hello_module.ko
xin@xin-desktop:~/mytest$ lsmod | grep hello_module
hello_module             593  0


ps:
不解决上面的warning,是可以编译成功的。但是在执行加载后
xin@xin-desktop:~/mytest$ sudo insmod hello_module.ko
报错:insmod: error inserting 'hellomod.ko': -1 Invalid module format
查了很多资料,普遍的观点是:
内核无法加载模块的原因是因为记载版本号的字符串(正规说法:版本印戳)和当前正在运行的内核模块的不一样,叫vermagic
此时,可用sudo tail /var/log/messages
你在最后一行应该看到类似下面的提示:
Dec 19 13:42:29 localhost kernel: hellomod: version magic '2.6.24.2 SMP mod_unload 686 4KSTACKS ' should be '2.6.27.7-134.fc10.i686 SMP mod_unload 686 4KSTACKS '
而我的只显示:
Mar 29 16:57:34 xin-desktop kernel: [ 6964.464931] hello_module: no symbol version for module_layout
但是通过modinfo和 uname -r的比较确实不一样

我按照提供的办法,修改源目录下的Makefie
把Makefile第1-4行的值改为当前内核一样的值
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 32
EXTRAVERSION = .54+drm33.21
NAME = Man-Eating Seals of Antiquity

确定你当前内核的值,通过
vi  /lib/modules/`uname -r`/build/Makefile

但是,我这样改过之后,还是又上面加载不上的问题,而且版本号跟写进Makefile的不是一样的,编译完成的是这样的:
2.6.32.57+drm33.23 SMP mod_unload modversions 586。
即便我把/usr/src/linux-2.6.32内核源码中的Makefile改了,也是这样的,我一直没有搞清楚,到底内核版本号是在哪里设置的。
最后,消除了这个warning后,虽然内核版本号仍不一样,但是可以加载了。
当前已经加载的内核模块video的信息:
xin@xin-desktop:~/mytest$ modinfo video
filename:       /lib/modules/2.6.32-38-generic/kernel/drivers/acpi/video.ko
license:        GPL
description:    ACPI Video Driver
author:         Bruno Ducrot
srcversion:     A52E70043443277D9757C8E
alias:          acpi*:LNXVIDEO:*
depends:        output
vermagic:      
2.6.32-38-generic SMP mod_unload modversions 586
parm:           brightness_switch_enabled:bool

hello_module的信息:
xin@xin-desktop:~/mytest$ modinfo hello_module.ko
filename:       hello_module.ko
alias:          a simplest module
description:    A simple Hello World Module
license:        Dual BSD/GPL
author:         xin
srcversion:     B757E1EEAD29F16BF0B6737
depends:        
vermagic:      
2.6.32.57+drm33.23 SMP mod_unload modversions 586

注意到 两者的vermagic是不一样的,但是可以加载hello_module.ko模块

c语言设置cpu affinity (设置程序需要使用的cpu内核) cpu mask

c语言设置cpu affinity (设置程序需要使用的cpu内核) cpu mask

编写一个简单的内核模块程序Hello World!

一、Linux内核模块基本原理Linux 内核模块(LKM)是一些在启动的操作系统内核需要时可以载入内核执行的代码块,不需要时由操作系统卸载。它们扩展了操作系统内核功能却不需要重新编译内核、启动系统。...
  • sh21_
  • sh21_
  • 2017年03月09日 16:47
  • 2128

Hello,Module 最简单的内核模块

第一个最简单的内核模块什么事都不做,仅在内核加载时打印 “ Hello module enter ” ,在模块卸载时打印 “ Hello module exit ” ,虽然什么事情也做不了,但这已经是...

Linux---我的第一个内核模块之Hello World

1、什么是内核模块? 内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),简称为模块。Linux内核之所以提供模块机...
  • L_in12
  • L_in12
  • 2015年11月04日 17:24
  • 727

第一个内核模块Hello.ko代码

第一个内核模块Hello.ko代码   1. 驱动代码hello.c的源码 #include #include   MODULE_LICENSE("Dual BSD/GPL");  ...

经典的第一个linux内核模块编程----hello,Kernel!

转自:http://edsionte.com/techblog/archives/1336学习内核模块编程,第一个小程序当然是hello,kernel!了,这应当算是一个惯例了。以前大三的时候在实验课...

linux 第一个内核模块Hello World

 内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个...

linux内核模块编译和安装--kni module移植的makefile

根据需要需要把依赖dpdk的kni module移植,所以就学习了下模块编译makefile,总结如下 Makefile内容如下 obj-m += rte_kni.o #要生成的module...

编译内核模块Hello World V3.0

经过V2.0我们的主根据地变为kangear_module这个目录中了,这次V3.0是将V2.0那一长串命令变为一个简单的make,其实唯一的办法就是写进Makefile中了,但是由V2.0中的关系图...
  • kangear
  • kangear
  • 2013年02月12日 22:15
  • 1566
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:内核模块学习--编译自己的第一个内核模块hello_module
举报原因:
原因补充:

(最多只允许输入30个字)