Chinaunix首页 | 论坛 | 博客
  • 博客访问: 235952
  • 博文数量: 48
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 480
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-24 11:02
文章分类

全部博文(48)

文章存档

2010年(33)

2009年(14)

2008年(1)

我的朋友

分类: LINUX

2009-10-24 20:22:11

驱动程序中lsmod命令实际读取的是/proc/modules文件
即与lsmod命令对应的结果是cat /proc/modules

内核中已经加载的模块的信息存在于/sys/module目录下

modprobe
命令比insmod命令要强大,它在加载某模块时会同时加载该模块所依赖的其他模块
使用modprobe -r filename的方式卸载将同时其依赖的模块
modinfo
模块名命令可以获得模块的信息
modinfo hello.ko

filename:       hello.ko
alias:          a simplest module
description:    A simple Hello World Module
author:         Jimmy
license:        Dual BSD/GPL
srcversion:     FC20E540C350C6F733C7546
depends:        
vermagic:       2.6.28-15-generic SMP mod_unload modversions 586


驱动模块参数,MODULE_PARM_DESC可以注解参数
如:
        static int num = 4000;
        module_param(num, int, S_IRUGO);
        MODULE_PARM_DESC(myshort, "A integer");

#include
#include

MODULE_LICENSE("Dual BSD/GPL");

static char *book_name = "dissecting Linux Device Driver";
static int num = 4000;
static int param[8] = {1, 2, 3, 4, 5, 6, 7, 8};
static int param_len = 8;

static int book_init(void)
{
        int i;
        printk(KERN_ALERT " book name: %s\n", book_name);
        printk(KERN_ALERT " book num: %d\n", num);
        for(i = 0; i < 8; i++)
        {
                printk(KERN_ALERT "param[%d] =  %d \n", i, param[i]);
        }

        return 0;
}

static void book_exit(void)
{
        printk(KERN_ALERT " Book module exit\n");
}

module_init(book_init);
module_exit(book_exit);
module_param(num, int, S_IRUGO);
module_param(book_name, charp, S_IRUGO);
module_param_array(param, int, ¶m_len, S_IRUGO);

MODULE_AUTHOR("Jimmy, fightingjimmy@gmail.com");
MODULE_DESCRIPTION("A simple Module for testing module params");
MODULE_VERSION("v1.0");

sudo insmod book.ko
dmesg
tail -10
[14047.901352]  book name: dissecting Linux Device Driver
[14047.901366]  book num: 4000
[14047.901377] param[0] =  1
[14047.901386] param[1] =  2
[14047.901388] param[2] =  3
[14047.901389] param[3] =  4
[14047.901390] param[4] =  5
[14047.901391] param[5] =  6
[14047.901392] param[6] =  7
[14047.901393] param[7] =  8

sudo rmmod book.ko
sudo insmod book.ko book_name='Hello' num=1000 param=8,7,6,5
[14298.942521]  book name: Hello
[14298.942535]  book num: 1000
[14298.942547] param[0] =  8
[14298.942558] param[1] =  7
[14298.942559] param[2] =  6
[14298.942560] param[3] =  5
[14298.942561] param[4] =  5
[14298.942562] param[5] =  6
[14298.942564] param[6] =  7
[14298.942565] param[7] =  8

sudo rmmod book.ko
sudo insmod book.ko book_name="Hello World" num=1000 param=8,7,6,5
insmod: error inserting 'book.ko': -1 Unknown symbol in module

dmesg
tail -10
[15097.587159] book: Unknown parameter `world'
猜想:可能是因为传入的字符串参数带有空格的原因(有遇到类似情况的请不吝赐教)

linux2.6
/proc/kallsyms文件对应着内核符号表,它记录了以及符号所在的内存地址。
EXPORT_SYMBOL(
符号名);
EXPROT_SYMBOL_GPL(
符号名);

module/
        include/
                print.h
        print/
                print.c
                Makefile
        symbol/
                test.c
                Makefile

/****************************************
* print.h                               *
*****************************************/
#ifndef PRINT_H
#define PRINT_H

void add_integer(int a, int b);
void sub_integer(int a, int b);

#endif


/****************************************
* print.c                               *
*****************************************/
#include
#include

#include "print.h"

MODULE_LICENSE("Dual BSD/GPL");

void add_integer(int a, int b)
{
        printk(KERN_ALERT " sum: %d\n", a + b);
}

void sub_integer(int a, int b)
{
        printk(KERN_ALERT " sub: %d\n", a - b);
}

EXPORT_SYMBOL(add_integer);
EXPORT_SYMBOL(sub_integer);


/****************************************
* test.c                                *
*****************************************/
#include
#include  
  
#include "print.h"  

MODULE_LICENSE("GPL");   
  
static int symbol_init(void)  
{
        printk(KERN_ALERT " Symbol test init\n");  
        add_integer(10, 6);
        sub_integer(10, 6);  
        return 0;  
}  
   
static void symbol_exit(void)  
{  
        printk(KERN_ALERT " Symbol test exit\n");  
}  
   
module_init(symbol_init);  
module_exit(symbol_exit);  

print
目录下的Makefile
obj-m := print.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
PRINT_INC = $(obj)/../include           
#包含print.h头文件
EXTRA_CFLAGS += -I $(PRINT_INC)

modules:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
        rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean


symbol
目录下的Makefile
obj-m := test.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
SYMBOL_INC = $(obj)/../include
EXTRA_CFLAGS += -I $(SYMBOL_INC)
KBUILD_EXTRA_SYMBOLS=$(obj)/../print/Module.symvers

modules:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
        rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

注意:若是Makefile文件中没有KBUILD_EXTRA_SYMBOLS=$(obj)/../print/Module.symvers
则需要将print目录下的Module.symvers拷贝到symbol目录下,这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看) 


分别编译insmod即可

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

chinaunix网友2010-12-13 19:16:40

楼主太厉害了.我以前写了一个小驱动,有3个ko,以前是直接静态编译到了内核中,现在有需求需要单独编译成 ko.然后,我今天分别写了3个Makefile,单独都生成了ko,但是,在insmod的时候,后面的ko依赖前面的 ko 中的符号,总是提示无法识别的symbol.然而,我在查看 /proc/kallsyms 的时候,可以找到引用的符号.很奇怪,尝试过很多方式,都不行.后来到现在快下班的时候,找到了楼主这篇文章,一试,还真是差 KBUILD_EXTRA_SYMBOLS.现在搞定了,太感谢楼主了~!~牛人~!~.这个知识点,都没有写到.楼主强人~!~