hello 内核模块

摘要:
“);}module_init;module_exit;1.在包含任何头文件之前,必须预定义符号__KERNEL__。此符号用于控制选择头文件的哪个部分。
#ifndef __KERNEL__
#  define __KERNEL__
#endif
#ifndef MODULE
#  define MODULE
#endif

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

MODULE_LICENSE("GPL");

static int year=2013;

MODULE_PARM(year,"i");

int hello_init()
{
	printk(KERN_WARNING"Hello World %d!
",year);
	return 0;
}


void hello_exit()
{
	printk("Hello Exit!
");
}

module_init(hello_init);
module_exit(hello_exit);

1.在包含任何头文件前,必须先预定义符号__KERNEL__,这个符号用于控制选择头文件的哪一部分。

2.另一个很重要的符号就是MODULE,必须在包含<linux/module.h>前定义这个符号,它用于告诉头文件,这是一个模块,如果编译进内核,必须去掉该定义。

3.模块加载函数(必需):安装模块时被系统自动调用的函数,通过module_init宏来指定。

4.模块卸载函数(必需):卸载模块时被系统自动调用的函数,通过module_exit宏来指定。

5.许可证申明(可选):宏MODULE_LICENSE被用来告知内核,该模块带有一个许可证,没有这样的说明,加载模块时内核会抱怨。有效的许可证有"GPL","GPL v2","GPL and additional rights","Dual BSD/GPL","Dual MPL/GPL"和“Proprietary"。

6.模块参数(可选):通过宏MODULE_PARM指定模块参数,模块参数用于在加载模块时传递参数给它。

    MODULE_PARM(name,type)有两个参数,name是模块参数的名称type是这个参数的类型,类型包括以下几种:

b:比特型    h:短整型    i:整型    l:长整型    s:字符串型

   在传递字符串型的参数时,这个模块参数需要在模块中用char* 来声明,系统会自动为其分配内存空间。

   例如:

       int a = 3;

       char* st;

       MODULE_PARM(a,"i");

       MODULE_PARM(st,"s");

7.模块的编译工作由gcc -c 命令来完成。例如:

#gcc -c -I/usr/src/linux-headers-2.6.32-48/include hello.c

8.加载 insmod    (insmod hello.o)

9.卸载 rmmod    (rmmod hell)

10.查看 lsmod

11.加载 modprobe

    modprobe如同insmod,也是加载一个模块到内核。它的不同之处在于它会查看要加载的模块,看它是否还依赖于其他模块,如果是modprobe找到这些模块,把他们先加载到内核。

12.为了确定模块是否可以被安全的卸载了,系统为每个模块保留了一个使用计数(lsmod可查看),用于记录正在使用该模块的用户数,只有当使用计数=0时,模块才可以被卸载。

 以下3个宏在内核中用来维护使用计数:

       MOD_INC_USE_COUNT:模块计数加1

       MOD_DEC_USE_COUNT:模块计数减1

       MOD_IN_USE:模块计数非0时返回真


内核模块开发过程中需特别注意以下几点:

1.在使用gcc编译模块时使用-c编译选项

2.在gcc编译选项中定义宏:_DMODULE和 -D__KERENL__

或直接在源文件中定义这两个宏:

  #define MODULE

  #define __KERNEL__

3.在使用gcc编译内核模块时,需要通过增加编译选项:-I/XXX/include  来指定内核源代码的头文件目录,并且还要保证内核源代码必须是配置过(make menuconfig),make dep过的。

注:XXX代表内核源代码的绝对路径,如:/usr/src/linux-headers-2.6.32-48/

4.版本不匹配

   内核模板的版本是由其所依赖的内核源代码版本所决定的,位于内核源代码所处的顶层Makefile中,如:

VERSION = 3
PATCHLEVEL = 9
SUBLEVEL = 2
EXTRAVERSION =

  当此版本与正在运行的内核版本(可通过uname -r 查询)不一致时,内核模块将无法插入内核。

解决办法:

1.使用insmod -f  强行插入

2.修改内核源代码顶层Makefile中的版本信息来与uname -r查看到的一致。

免责声明:文章转载自《hello 内核模块》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇asp.net父窗口、子窗口【转帖】Explorer参数详解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux磁盘分区格式化挂载

  1,Linux分区 原理 1)Linux无论有几个分区,分给哪一目录使用,归根结底只有一个根目录,一个独立且唯一的文件结构,Linux中每个分区都是用来组成整个文件系统的一部分。 2)Linux中采用了一种叫 “载入” 的处理方法,它的整个文件系统中包含了一整套的文件和目录,且将一个分区和一个目录联系起来。这时要载入的一个分区将使它的存储空间在一个目...

VMware虚拟机Linux增加磁盘空间的扩容操作

转载自点击打开链接 用VMwareware虚拟机安装的Red Hat Enterprise Linux系统剩余空间不足,造成软件无法正常安装。如果重新装一遍系统就需要重新配置好开发环境和软件的安装配置。通过上网搜集的资料,结合自己的实践,总结了如下扩大硬盘空间的详细步骤,希望对大家有帮助。 (1)打开VMware,选择Edit Virtual mache...

linux 系统中awk命令实现统计每行数据的最大值、最小值

1、测试数据 root@PC1:/home/test# ls test.txt root@PC1:/home/test# cat test.txt 3 4 2 2 1 9 5 7 5 7 8 4 2 3 4 6 2、统计每行数据的最大值 root@PC1:/home/test# ls test.txt root@PC1:/home/test# cat te...

第一步(搭建阿里云主机服务器): 如何在远程Linux服务器上搭建Nginx

首先得申明一下使用的工具有: 1. putty https://pan.baidu.com/s/1i4Ix8Hn 2. fileZilla https://pan.baidu.com/s/1nvJR8al 如果是抢购阿里云免费的就按照下面执行下去就行了,如果花钱买的主机,会顺手送你一个Apache服务器,你的手动卸载Apache,卸载的步骤 rpm -q...

Visual Studio 2013新建工程导入现有代码文件夹并且保持目录结构

本文提供了一个在Windows环境下使用Visual Studio 2013编辑现有源代码并且保持目录结构的方法。本文使用VS2013中文社区版做示例(本版本为免费版,可在VS官网下载),其他版本的VS操作方式类似。打开VS2013,选择【菜单】-【新建】-【从现有代码创建项目】 选择项目类型:Visual C++ 项目文件位置:创建完成后会在这个目录生成...

Qt程序用dpkgbuildpackages打包Linux技术文档 diybl

Qt程序用dpkg-buildpackages打包-Linux技术文档 - diybl Qt程序用dpkg-buildpackages打包www.diybl.com 时间 : 2010-06-10 作者:匿名 编辑:壹枝雪糕 点击: 288 [ 评论 ]我们一般写的Qt程序如果用dpkg-buildpackages来进行打包的话,会遇到一些问题。dh_ma...