Chinaunix首页 | 论坛 | 博客
  • 博客访问: 334988
  • 博文数量: 72
  • 博客积分: 2130
  • 博客等级: 大尉
  • 技术积分: 857
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-05 16:10
文章分类

全部博文(72)

文章存档

2010年(5)

2009年(14)

2008年(53)

分类: LINUX

2008-10-31 14:52:54

  1. 模块就是能用命令进行加载到内核或从内核卸载的程序,它们可以使机器在不重启的情况下可以扩展内核功能,其中一种模块类型就是驱动,可以用lsmod命令来查看什么模块已经被加进内核。

  2. 当内核需要一个不是驻留在内核里的模块时,它会执行modprobe命令去把模块加载上,而传递给modprobe命令的参数有两种形式,如char-major-180-* usbcore,该种形式定义在/etc/modprobe.d/aliases中,对应的模块名为usbcore.ko,然后modprobe将去查看一下/lib/modules/version/modules.dep看是否有模块必须在加载该模块之前加载,该文件是由depmod -a命令生成的,是关于模块依赖性的,最后modprobeinsmod命令把依赖的模块加载上,再把该模块加载上。

  3. 在内核2.3.13之前,内核模块必须有两个功能:初始化功能(init_module()),它是当模块被加载到内核时调用的;卸载功能(cleanup_module()),它是当模块被卸载之前调用的。现在可以用任何名字来实现一个模块的初始化或卸载,但每一个内核模块都必须包含linux/module.h

    如果你要用到一些宏扩展如prink(),还需要包含linux/kernel.h

  4. 简单模块例子:

    hello.c

    #include

    #include

    #include

    MODULE_LICENSE("Dual BSC/GPL");

    MODULE_AUTHOR("Sam Shen ");

    MODULE_DESCRIPTION("Test Module Program");

    MODULE_SUPPORTED_DEVICE("Hello,world");

    static int _ _init hello_init(void)

    {

    printk(KERN_ALERT"Hello, world!\n");

    return 0;

    }

    static void _ _exit hello_exit(void)

    {

    printk(KERN_ALERT"Goodbye, cruel world!\n");

    }

    module_init(hello_init);

    module_exit(hello_exit);

    Makefile

    obj-m += hello.o

    KERNELDIR:=/lib/modules/$(shell uname -r)/build

    PWD=$(shell pwd)

    all:

    make -C $(KERNELDIR) M=$(PWD) modules

    clean:

    make -C $(KERNELDIR) M=$(PWD) clean

    (想了解更多关于编译模块,请查看linux/Documentation/kbuild/modules.txt,更多关于内核模块的Makefile,请查看linux/Documentation/kbuild/makefiles.txt)

    _ _ init声明是当init函数执行完成后内核能够回收空间,_ _initdata和它有相同的功能,但是是对于变量而不是函数的, _ _exit声明是为了内核能够省略掉cleanup函数,它们可装载模块不受影响。MODULE_*定义在linux/include/linux/module.h,它们不被内核本身使用,只是为了让一些工具查看模块的信息。

    Ctrl+Alt+F5,进入tty5,用modinfo hello.ko查看模块的信息,用sudo insmod hello.ko加载模块,用lsmod | grep hello查看模块是否已加载上,用sudo rmmod hello卸载该模块。所有已经加载的模块都列在文件/proc/modules中,故也可以通过查看hello是否出现在该文件中来判断模块是否已经加载上,一般刚加载的模块加在第一行,如:hello 2432 0 - Live 0xf8974000 (P),其中hello为模块名,2432是模块大小,0是使用数目,-Live是模块状态,0xf8974000是模块位置,(P)为非标准内核模块。

  5. 可以给模块传递命令行参数,但不是用argc/argv的机制,而是用module_param()module_param_array()宏,它们定义在include/linux/moduleparam.h文件中,使用范例:

    hello.c

    #include

    #include

    #include

    #include

    #include

    MODULE_LICENSE("Dual BSC/GPL");

    MODULE_AUTHOR("Sam Shen ");

    MODULE_DESCRIPTION("Test Module Program");

    MODULE_SUPPORTED_DEVICE("Hello,world");

    static short int myshort = 1;

    static int myint = 2;

    static long int mylong = 8888;

    static char *mystring = "shenxiaocheng";

    static int myintArray[2] = {-1, 1};

    static int arr_argc = 0;

    module_param(myshort, short, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);

    MODULE_PARM_DESC(myshort, "A short integer");

    module_param(myint, int, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);

    MODULE_PARM_DESC(myint, "An integer");

    module_param(mylong, long, S_IRUSR);

    MODULE_PARM_DESC(mylong, "A long integer");

    module_param(mystring, charp, 0000);

    MODULE_PARM_DESC(mystring, "A character string");

    module_param_array(myintArray, int, &arr_argc,0000);

    MODULE_PARM_DESC(myintArray, "An array of integer");

    static int __init hello_init(void)

    {

    int i;

    printk(KERN_ALERT"Hello, world!\n");

    printk(KERN_ALERT"myshort is a short interger: %hd\n",myshort);

    printk(KERN_ALERT"myint is an integer %d\n", myint);

    printk(KERN_ALERT"mylong is a long integer: %ld\n",mylong);

    printk(KERN_ALERT"mystring is a string: %s\n", mystring);

    for(i=0; i<(sizeof myintArray / sizeof(int)); i++)

    printk(KERN_ALERT"myintArray[%d] = %d\n", i, myintArray[i]);

    printk(KERN_ALERT"got %d argumeters for myintArray.\n", arr_argc);

    return 0;

    }

    static void __exit hello_exit(void)

    {

    printk(KERN_ALERT"Goodbye, cruel world!\n");

    }

    module_init(hello_init);

    module_exit(hello_exit);

    加载时,可以用sudo insmod hello.ko myshort=5命令为模块传递参数。

    如果我们把hello_inithello_exit函数分开放在start.cstop.c文件中,则Makefile需要改为

    obj-m += startstop.o

    startstop-objs := start.o stop.o

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