Linux内核基础

操作系统内核模块:

Linux内核是整体式结构,各个子系统联系紧密,作为一个大程序在内核空间运行。

image

Linux内核模块体系结构:

Linux内核引入内核模块机制。通过动态加载内核模块,使得在运行过程中扩展内核的功能。不需要的时候,卸载该内核模块。

image

Linux内核子系统

image

写内核程序需要注意:

image

Hello模块

/*hello.c*/

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
static int __init hello_init(void)
{
    printk("hello init.\n");
    return 0;
}
static void __exit hello_exit(void)
{
    printk("hello exit.\n");
}
MODULE_INIT(hello_init);
MODULE_EXIT(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("spron");
MODULE_DESCRIPTION("hello world modules");

内核模块的Makefile:
CONFIG_HELLO_WORLD ?= m     //配置变量,用模块的方式编译
ifneq ($(KERNELRELEASE),)       //如果这个变量是有定义的话,执行
    hello_world-objs := hello.o  a.o  b.o
    obj-$(CONFIG_HELLO_WORLD) += hello_world.o     //告诉内核要产生的文件为XXX.O
else
    KERNELDIR = /$(your_kernel_source)/ 内核的源代码的目录     //如:KDIR=/root/LINUX
    PWD := $(shell pwd)  //执行当前目录的命令
    modules:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules      //生成内核模块参数为内核源代码目录以及模块所在目录
endif
clean:
    rm –rf  *.o  *~ core  .depend .  *.cmd  *.ko  *.mod.c  .tmp_versions
注意: your_kernel_source,是你的linux kernel源代码的目录

编译加载/卸载:
在hello world模块目录上
#make
得到hello_world.ko就是产生的内核模块,在评估板上使用 #insmod hello_world.ko 和 #rmmod hello_world 观察控制台输出的结果。

内核模块证书和内核模块文档说明:
2.4内核后,引入识别代码是否在GPL许可下发布的机制 。在使用非公开的源代码产品时会得到警告。通过宏MODULE_LICENSE(“GPL”),设置模块遵守GPL证书,取消警告信息。
MODULE_DESCRIPTION()用来描述模块的用途。
MODULE_AUTHOR()用来声明模块的作者。
MODULE_SUPPORTED_DEVICE() 声明模块支持的设备。
这些宏都在头文件linux/module.h定义。使用这些宏只是用来提供识别信息。

模块参数:
module_param(name,type,perm);
    perm是一个权限值,控制谁可以存取模块参数在 sysfs 中的表示。
    perm 被设为 0, 就根本没有 sysfs 项
这个宏定义应当放在任何函数之外, 典型地是出现在源文件的前面。
应该总是为变量赋初值。
宏MODULE_PARM_DESC() 用来注解该模块可以接收的参数。该宏两个参数:变量名和一个对该变量的描述。
模块可以用这样的命令行加载:./insmod mymodule.ko myvariable=2

__init、__initdata和__exit、__exitdata
对于__init、__initdata和__exit、__exitdata的定义位于<linux/init.h>,这些宏定义的作用是告诉编译器将这些函数或者数据放入相应的section中,
而在模块加载的阶段,.ko文件中的代码和数据的加载区域是根据section来加载的。比如:如果函数的定义中带有__init,那么这个函数的所有代码会被放入.init.text的section中。如果函数的定义中带有__initdata,那么这个函数的所有代码会被放入.init.data的section中。
之所以要使用这个宏定义,其中一个原因是标记为初始化的函数和数据,表明该函数和数据仅在初始化期间使用。
在模块装载之后,模块装载就会将初始化函数扔掉。这样可以将该函数占用的内存释放出来。
详细的说明见详细文档下载链接中的“__init,__initdata,__exit,__exitdata.doc文档” 。

详细文档及代码下载链接: http://download.csdn.net/detail/klcf0220/5760109

posted @ 2013-07-15 22:48  不止所见  阅读(774)  评论(0编辑  收藏  举报