Chinaunix首页 | 论坛 | 博客
  • 博客访问: 428752
  • 博文数量: 123
  • 博客积分: 2686
  • 博客等级: 少校
  • 技术积分: 1349
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-23 22:11
文章分类
文章存档

2012年(3)

2011年(10)

2010年(100)

2009年(10)

我的朋友

分类: LINUX

2010-02-25 14:08:45

环境:Fedora 12
内核:Linux-2.6.32.2
 
一、实验
STEP 1:新建一个文件hello.c,内容如下:
 

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("DUAL BSD/GPL");

static int hello_init(void)
{
    printk(KERN_ALERT "hello,world\n");

    return 0;

}

static void hello_exit(void)

{

    printk(KERN_ALERT "goodbye,kernel\n");

}

module_init(hello_init);

module_exit(hello_exit);


STEP 2:在hello.c的同一个目录下,新建一个Makefile,内容如下:
 

obj-m := hello.o

KERNELBUILD := /lib/modules/`uname -r`/build

default:

     make -C $(KERNELBUILD) M=$(shell pwd) modules

clean:

     rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions


STEP 3:编译,执行make 命令。

STEP 4:装载模块。

insmod hello.ko


STEP 5:卸载模块。

rmmod hello.ko


STEP 6:查看系统日志文件。printk函数把内容写入了/var/log/messages里面了。

cat /var/log/messages


二、对实验的理解
 
Q1:为什么模块能够调用printk函数?
在insmod函数装入模块后,模块就连接到了内核,因而可以访问内核的公用符合表。
 
Q2:操作模块的相关命令?
insmod xx.ko   //将模块的代码和数据装入内核,然后使用内核的符合表解析模块中未解析的符号
rmmod  xx.ko   //从内核中移除模块
lsmod          //通过读取/proc/modules,打印出当前装载到内核中的模块
modprobe xx.ko //解析依赖性功能+insmod
 
Q3:什么是内核符号表?
insmod通过内核符号表来解析模块中未定义的符号。公共内核符号表包含了所有的全局内核项(函数和变量)的地址。当模块被装入内核后,他所导出的任何符号都会变成内核符号表的一部分。新模块可以使用我们自己导出的符号表,从而可以用一个个模块堆叠出一个新的模块,此为模块层叠技术。
   如果一个模块需要向其他模块导出符号,则应该使用下面的宏:
     EXPORT_SYMBOL(name);
     EXPORT_SYMBOL_GPL(name);
 
Q4:所有模块都应该包含的头文件?
#include        //包含有可装载模块需要的大量符号和函数的定义
#include          //指定初始化和清除函数
#include   //在装载模块时向模块传递参数,需要这个头文件
……                             //其他头文件根据具体需要再加入
 
Q5:Makefile做了哪些事情?
 

#表明模块是由目标文件hello.o组成

obj-m := hello.o

#定义了一个变量,表示模块所在的目录,uname -r的结果为当前运行的内核版本
KERNELBUILD := /lib/modules/`uname -r`/build

#-C 的作用是改变目录到 $(KERNELBUILD)指定的位置;M=的作用是让该makefile在构造#modules之前返回到模块源代码目录;modules为make的目录,记得编译内核时有一步是 #make modules。总结,make modules发生的地方在${KERNELBUILD},在make moddules之 #前make编译的地方在${shell pwd}
default:
     make -C $(KERNELBUILD) M=$(shell pwd) modules

#删除make生成的文件
clean:

     rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions


 
Q6:模块参数相关?(来源于:http://blog.chinaunix.net/u1/55468/showart_2151108.html

用户空间的应用程序可以接受用户的参数,LKM也可以做到,只是方式有些不同而已。相关的宏有:

MODULE_PARM(var, type);
MODULE_PARM_DESC(var, "the description of the var");

模块参数的类型(即MODULE_PARM中的type)有一下几种:

  • b byte(unsigned char)
  • h short
  • i int
  • l long
  • s string(char*)

这些参数最好有默认值,如果有些必要参数用户没有设置可以通过在module_init指定的init函数返回负值来拒绝模块的加载。 LKM还支持数组类型的模块,如果在类型符号前加上数字n则表示最大程度为n的数组,用“-”隔开的数字分别代表最小和最大的数组长度。

示例:
MODULE_PARM(var, "4i"); // 最大长度为4的整形数组
MODULE_PARM(var, "2-6i"); // 最小长度为2,最大长度为6的整形数组

如何用insmod传入参数,其实man一下就可以了,不过现在的man有些过于简单,所以在此说明一下:

insmod variable=value[,value2...] ...

其中value可以用引号括起来,也可以不用。但是有一点“=”前后不能留有空格,并且value中也不能有空格。

三、带参数的模块加载和卸载实验

STEP 1:把hello.c的代码改为如下:

(根据http://blog.chinaunix.net/u1/55468/showart_2151108.html修改)

/*file: hello.c*/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>

MODULE_AUTHOR("xiaosuo ");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("This module is a example.");
static int int_var = 0;
static const char *str_var = "default";
static int int_array[6];
module_param(int_var, int,S_IRUGO);
//MODULE_PARM_DESC(int_var, "A integer variable");
module_param(str_var, charp,S_IRUGO);
//MODULE_PARM_DESC(str_var, "A string variable");
module_param_array(int_array,int,5,S_IRUGO);
//MODULE_PARM_DESC(int_array, "A integer array");
static int __init hello_init(void)
{
        int i;
        printk(KERN_ALERT "Hello, my LKM.\n");
        printk(KERN_ALERT "int_var %d.\n", int_var);
        printk(KERN_ALERT "str_var %s.\n", str_var);
        for(i = 0; i < 6; i ++){
                printk("int_array[%d] = %d\n", i, int_array[i]);
        }
        return 0;
}
static void __exit hello_exit(void)
{
        printk(KERN_ALERT "Bye, my LKM.\n");
}
module_init(hello_init);
module_exit(hello_exit)

STEP 2:make

STEP 3:输入命令insmod hello.ko int_var=1001.

STEP 4:查看int_var的值是否是我们输入的值:cat /var/log/messages.

 

参考:《Linux设备驱动程序》

      http://blog.chinaunix.net/u1/55468/showart_2151108.html

下一篇博客:linux驱动程序2,将主要分析文件的本质,驱动程序与文件系统接口,内核和应用程序是如何交互的,应用程序对设备的操作是怎样具体一步步深入到硬件设备的。
阅读(1214) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~