内核模块学习--编译自己的第一个内核模块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模块

Linux模块编程机制之hello kernel

作者:bullbat                看了那么多理论知识,可能还是一头雾水,是啊,纯理论分析本来就不好理解。为了更好的理解Linux内核各种内部机制以及其运用,在接下来的学习中将采用...
  • bullbat
  • bullbat
  • 2012年03月13日 11:10
  • 8315

LinuxDriver1HelloModule

Hello ModuleLinux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载:  (1)直接编译进Linux内核,随同Linux启动时加载;  (2)编译成一个可加载...
  • braveyly
  • braveyly
  • 2011年07月28日 13:20
  • 814

Linux 最简单内核模块 Hello World 示例

注:如果想要按照本篇实践,需要有能运行的arm开发板和对应版本的内核(如果想在Linux主机上编译运行,请参考附1) 1. 在相应版本内核的driver目录下新建如下文件: module fil...
  • chinaeran
  • chinaeran
  • 2015年04月28日 08:38
  • 6118

insmod: ERROR: could not insert module module.ko: Invalid parameters

关于向内核插入模块的时候,遇到了这个错误,起初一直怀疑是insmod使用不正确,或是内核版本不支持,后来发现有两个方面的原因: 一:需要将生成的 .ko 文件拷贝到 /lib/modules/4.4...
  • u013095333
  • u013095333
  • 2016年09月07日 11:11
  • 3288

NetMap编译搭建

netmap是Luigi Rizzo(牛人)在FreeBSD和linux下一个高性能抓包的平台.  据说在单核900MHZ的CPU上就能跑出14.8Mpps的性能.         前段时间配置研究了...
  • thanfur
  • thanfur
  • 2013年10月23日 14:11
  • 5351

如何编译内核ko

如何编译内核ko
  • yzytr
  • yzytr
  • 2017年08月28日 23:33
  • 237

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

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

第一个内核模块程序编译

1.创建内核模块源文件hello_printk 代码如下: #include #include static int __init hello_init(void) { printk("Hell...
  • yainyiyi123
  • yainyiyi123
  • 2016年10月30日 18:37
  • 324

开始编译内核模块

http://bbs.nfvdr.com/thread-4917-1-1.html   环境:debian 5.00 内核 2.6.26-1-686 问题:使用内核包编译驱动时常常提示如下: ...
  • wwyyxx26
  • wwyyxx26
  • 2011年04月15日 15:31
  • 9695

Linux内核模块创建

本文包含了以下四个方面的信息: --怎样构建一个外部模块 --怎样使用的你的kbuild结构编译/建造(make)一个模块 --Kbuild如何安装一个内核 --怎样在一个非标准的位置安装一个...
  • cupidove
  • cupidove
  • 2014年10月29日 10:33
  • 1727
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:内核模块学习--编译自己的第一个内核模块hello_module
举报原因:
原因补充:

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