3-05 嵌入式Linux内核模块开发

(本节笔记的实验代码,在这里

一.  内核模块基础

1.  基本概念
  Linux内核的整体结构非常庞大,使用组件的方法分为两种,一是把组件编译进内核文件(zImage或uImage),但会导致占用内存过多;二是把需要用到的内核组件在需要用到的时候通过动态的方式加载进内核。
  内核模块本身并不被编译进内核文件,可以根据需求,在内核运行期间动态地安装或卸载,因此,可以更加有效的节省内存空间。


2.  安装于卸载
  2.1  安装 insmod
    例如:insmod /home/dnw_usb.ko
  2.2  卸载 rmmod
    例如:rmmod dnw_usb  //注意不是dnw_usb.ko
  2.3  查看 lsmod
    例如:lsmod


二.  内核模块设计

1.  内核模块三个要素
  1.1  头文件  <linux/init.h>  <linux/module.h>
  1.2  加载函数  module_init
  1.3  卸载函数  module_exit


2.  范例代码  touch helloworld.c

  #include <linux/init.h>
  #include <linux/module.h>


  static int hello_init()
  {
      printk(KERN_WARNING"hello world!\n");  //提示性信息以便用WRNING优先级
      return 0;
  }


  static void hello_exit()
  {
      printk(KERN_WARNING"hello exit!\n");
  }


  module_init(hello_init);
  module_exit(hello_exit);
                                                             


3.  编写Makefile,编译内核模块
  3.1   touch Makefile

  obj-m := helloworld.o
  KDIR := /arm/linux 2.6.30.4   //模块所依赖的宿主机上内核源码目录
  all:
       make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
  clean:
          rm -f *.o *.ko *.order *.symvers
                                      


  obj-m := hello.o  //若是file1.o file2.o file3.o等多个文件
  hello-obj := file1.o file2.o file3.o
  ......
                                                              』
  3.2  编译和使用内核模块
    #make
    #cp helloworld.ko /arm/rootfs
    //启动开发板并通过启动NFS rootfs
    #insmod helloworld.ko
    hello world!
    #rmmod helloworld.ko
    hello exit!


三.  内核模块可选项

1.  模块声明

 1.1   MODULE_LICENSE(“遵守的协议”)

    申明该模块遵守的许可证协议,如:“GPL”、“GPL v2”等。

 1.2  MODULE_AUTHOR(“作者”)

    申明模块的作者。

 1.3   MODULE_DESCRIPTION(“模块的功能描述”)

    申明模块的功能

 1.4   MODULE_VERSION(“版本”)

    申明模块的版本,如“V1.0”等。

 1.5范例代码


 #include <linux/init.h>

 #include <linux/module.h>

 

 MODULE_LICENSE("GPL");   //声明遵守的许可证协议

 

 static int hello_init()

 {

      printk(KERN_WARNING"helloworld!\n"); 

      return 0;

 }

 

 static void hello_exit()

 {

      printk(KERN_WARNING"helloexit!\n");

 }

 

 module_init(hello_init);

 module_exit(hello_exit);                                                            

 

2.  模块参数

     类似于int main(int argc, char** argv)。方法是:通过宏module_param制定保存模块参数的数量。模块参数用于在加载模块时传递参数给模块。格式为module_param(name,type,perm)

name:变量的名称

type:  变量类型,bool:布尔型,int:整形,charp:字符型

perm是访问权限,S_IRUGO:度权限,S_IWUSR:写权限

例如:int a =3;

      char *st;

      module_param(a,int,S_IRUGO);

      module_param(s,charp,S_IRUGO);

 


 #include <linux/init.h>

 #include <linux/module.h>

 

 MODULE_LICENSE("GPL"); 

 int a = 3;

 char *p;

 module_param(a, int, S_IRUGO | S_IWUSR); //声明模块参数

 module_param(p, charp, S_IRUGO | S_IWUSR);

 static int hello_init()

 {

      printk(KERN_WARNING"helloworld!\n");

      printk("a = %d\n",a);

      return 0;

 }

 

 static void hello_exit()

 {

      printk(KERN_WARNING"helloexit!\n");

 }

 

 module_init(hello_init);

 module_exit(hello_exit);

                                                             

 在加载的时候输入:#insmod helloworld.ko a=10

                    #rmmod helloworld

                    #insmod hellorld.ko p=abcd

                    #rmmod helloworld

 

3.  符号输出

 在一个模块内(a.ko)使用了另外一个模块(b.ko)内的函数,除了a.ko中要用extern引用需要调用的b.ko中的函数以外,b.ko要声明该函数要被其他模块调用(EXPORT_SYMBOL(函数名))。

 在嵌入式Linux系统中,必须先装载 b.ko,然后才能装载 a.ko,卸载也是,必须先卸载a.ko,然后在卸载b.ko,因为a.ko依赖于b.ko。

touch helloworld.c

  #include <linux/init.h>

 #include <linux/module.h>

 

 MODULE_LICENSE("GPL"); 

 

 extern add(int a, int b);    //声明add函数

 

 static int hello_init()

 {

      printk(KERN_WARNING"helloworld!\n");

      a = add(1, 4)    //引用add.ko中的add函数,只能在hello_init中调用

      printk("a = %d\n",a);

      return 0;

 }

 

 static void hello_exit()

 {

      printk(KERN_WARNING"helloexit!\n");

 }

 

 module_init(hello_init);

 module_exit(hello_exit);

                                                             』

 

touch add.c

 #include <linux/init.h>

 #include <linux/module.h>

 

 MODULE_LICENSE("GPL"); 

 

 int add(int a, int b)

 {

      return a+b;

 }

 

 static int hello_init()

 {

      return 0;

 }

 

 static void hello_exit()

 {

 }

 

 EXPORT_SYMBOL(add);  //声明add()会被其他模块加载

 module_init(hello_init);

 module_exit(hello_exit);

                                                             』

touch Makefile(注意PWD为大写)

 obj-m := helloworld.o add.o

 KDIR := /arm/linux 2.6.30.4 

 all:

         make -C $(KDIR) M=$(PWD) modules ARCH=armCROSS_COMPILE=arm-linux-

 clean:

          rm -f *.o *.ko *.order *.symvers









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值