Chinaunix首页 | 论坛 | 博客
  • 博客访问: 582854
  • 博文数量: 165
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1554
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-23 22:57
个人简介

我本仁慈,奈何苍天不许

文章分类

全部博文(165)

文章存档

2018年(1)

2016年(33)

2015年(5)

2014年(34)

2013年(92)

分类: LINUX

2013-12-26 16:45:05

Linux内核模块开发

{//?什么是内核模块   

  可在运行时添加到内核中的代码被称为“模块”。

{//?内核模块和应用程序有何不同

         应用            --             模块

    从头到尾单任务              预先注册进内核,被动的被调用的              

     应用空间                    内核空间,权限大

   段错误对系统危害小          段错误常会导致系统崩溃

}

}

{//?为何要用内核模块

  1、减小内核体积,因为模块本身不被编译到内核镜像里面。

  2、可以在内核中添加或删除功能而不用重新编译内核

}

{//?重点在那

掌握如何去创建和使用一个内核模块

}

{//?一个最简单的内核模块如何实现和使用的  重点

//---/hello_module/hello.c

  #include  // for module_init  __init

  #include  // for MODLE_LICENS

  #include 

  

  MODULE_LICENSE ("GPL");    //模块许可声明, 如果没GPL回导致报错内核被污染,或调用不了

  static int __init hello_init (void)     // 为安全起见,模块中使用的函数都用static,   

                                          /* __init  标记其后面的函数和数据被放入特定段中。

                                             当模块被装载后,该函数会被仍掉,以释放其占用的内存。

                                           */

  {

     printk("Hello world\n");

     return 0;

  }

  

  static void __exit hello_exit (void)    

  {

     printk("Goodbye world\n");

  }

  module_init (hello_init); //模块加载入口声明

  module_exit (hello_exit); //模块卸载入口声明

  

  //---Makefile

  ifeq ($(KERNELRELEASE),)      /* 如果KERNELRELEASE 未定义则执行下面语句

                                   (KERNELRELEASE 是内核源码的顶层Makefile定义的变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义)*/

  KERNELDIR ?= /lib/modules/$(shell uname -r)/build      //linux 内核源码位置 这里是指ubuntu 

  #KERNELDIR ?= /root/linux-2.6.35                       //对应arm板子的内核源码

  PWD := $(shell pwd)

  

  all:                                //make 时从该目标执行

          $(MAKE) -C $(KERNELDIR) M=$(PWD) modules   /* -C  $(KERNELDIR)   跳转到内核源码目录下读取那里的Makefile

                                                        M=$(PWD)           返回到当前目录继续读入、执行当前的Makefile,而此时 KERNELRELEASE已被定义

                                                                           故执行下面的obj-m := hello.o 生成.ko 模块文件

                                                        最后的modules      它指向的是读入的kernel顶层Makefile里的modules                   

                                                      */

  clean:                                              //清除编译生成的文件

          rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*

  

  else

      obj-m := hello.o    //指明用目标文件hello.o 建立一个模块文件hello.ko 

  endif

//---使用

#make                //编译生成模块文件hello.ko

#file hello.ko       //查看一下格式,看编译的是 电脑的(Intel 80386), 还是板子的(ARM)

  #insmod hello.ko     //加载模块  ,另用modprobe也可,它会自动加载依赖的模块

                       /*

                       可能保错 insmod: can't insert 'hello.ko': invalid module format 

                       原因就是格式不对(file hello.ko可查看)如编译的是电脑的hello.ko 缺放到板子上运行。 

                       */

  #lsmod | grep hello  //检测是否已加载  , lsmod 实际是读取/proc/modules

  #rmmod hello         /*卸载模块     

                        在板子上可能报错 rmmod: chdir(/lib/modules): No such file or directory 

                                         rmmod: chdir(2.6.35-g9c29226-dirty): No such file or directory 

                        需要建立对应的/lib/modules/2.6.35-g9c29226-dirty 目录

                        当报 rmmod: module 'hello' not found ,原因是

                        busybox制作时选择简单module配置,会找/lib/modules 让内核导出依赖关系文件,所以rmmod 会坚持依赖关系,

                        其实已经卸载成功了的,可不必理会

                       */

  #dmesg               //查看打印的信息

  

}

{//---扩展

 1. 添加模块参数

    static int myint = 420; 

    module_param (myint, int, 0400); //添加模块参数, 参数名,参数类型,参数读/写权限  

    #insmod hello.ko  myint=500

    #dmesg

 2. 附加一些模块信息

    MODULE_AUTHOR("Song Baohua");   //作者是谁

    MODULE_DESCRIPTION("A simple Hello World Module"); //模块信息描述

        

    #modinfo hello.ko   //查看驱动模块信息

 3. 模块间函数调用

    //--module1.c

    static int func1(void)

    EXPORT_SYMBOL(func1);   //EXPORT_SYMBOL 宏用于将符号导出到内核符号表/prob/kallsyms

                            //导出的符号,其他模块可使用,但要声明extern int func1(void);

    //--module2.c

    extern int func1(void);

    static int func2(void)

    {

     func1();

    } 

}

阅读(1027) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~