HelloWorld_module.c

0. Linux系统环境,内核2.6.18(内核版本要保证2.6才能保证下面的可用),操作系统debian(这个对代码无影响,Makefile编写时可能会对路径有影响)

1.代码示例
/*---------------------------
HelloWorld_module.c
------------------------------*/

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

static char *whom = "world";
module_param(whom, charp, 0);//charp为指针参数类型
static int howmany = 1;
module_param(howmany, int, 0);

static int hello_init(void)
{
 int i;
 for( i=0; i<howmany; i++)
  printk(KERN_ALERT "(%d) Hello, %s!/n",i,whom);
 return 0;
}

static void hello_exit(void)
{
 printk(KERN_ALERT "Goodbye!/n");
}

module_init(hello_init);
module_exit(hello_exit);

/*------------------------------
          Makefile
-------------------------------*/
obj-m += HelloWorld_module.o

all:
        make -C /usr/src/linux-source-2.6.18-P0 M=$(PWD) modules
clean:
        make -C /usr/src/linux-source-2.6.18-P0 M=$(PWD) modules clean


2.编译,加载与卸载
 
 编译,将会生成四个文件分别是 HelloWorld_module.o  HelloWorld_module.ko     HelloWorld_module.mod.o HelloWorld_module.mod.c
# make
 加载模块
# insmod HelloWorld_module.ko
如果成功,那么
#lsmod
将会看到系统的模块列表中出现HelloWorld_module模块,运行命令#
dmesg
会在尾部看到
(0)Hello,world
当然如果使用参数将会出现另外的结果例如 insmod HelloWorld_module.ko howmany=2 whom=Glory,将会得到
(0)Hello,Glory
(1)Helllo,Glory

模块卸载,在dmesg执行后会发现尾部多出了一个Goodbye!
#rmmod hello.ko

3.几点说明
(1). module_param()用于传递命令行参数,关于module_param()详细说明可以查看http://hi.baidu.com/zkheartboy/blog/item/18138a82d07f3cba6c81199e.html
(2) .Makefile文件命名,保证第一个字母大写,其它小写(Makefile文件都如此),大小写敏感(Linux中皆如此),Makefile中make命令之前为Tab键,而不是空格,/usr/src/linux-

source-2.6.18-P0不一定每个人的机器都如此,但要指向Linux的内核代码树所在目录
(3).printk()并不是设计用来同用户交互的,虽然我们在 hello-1就是出于这样的目的使用它!它实际上是为内核提供日志功能, 记录内核信息或用来给出警告。因此,每个printk() 声明都

会带一个优先级,就像你看到的KERN_ALERT 那样。内核总共定义了八个优先级的宏, 所以你不必使用晦涩的数字代码,并且你可以从文件 linux/kernel.h查看这些宏和它们的意义。如果

你 不指明优先级,默认的优先级DEFAULT_MESSAGE_LOGLEVEL将被采用。八个优先级分别是(使用宏定义和使用<数字>效果一样)
KERN_EMERG <0>
KERN_ALERT <1>
KERN_CRIT <2>
KERN_ERR <3>
KERN_WARNING <4>
KERN_NOTICE <5>
KERN_INFO <6>
KERN_DEBUG <7>
(4).一个内核模块应该至少包含两个函数。一个“开始”(初始化)的函数被称为module_init() 还有一个“结束” (干一些收尾清理的工作)的函数,module_exit(),这两个函数的参数都是函数指

针,可以保证用户随意的定义函数的实现和函数名称,在这里指向相应的实现即可,示例代码中分别是hello_init和hello_exit
(5)MODULE_LICENSE("GPL"),加入这行代码是为了防止后面出现缺少证书的警告。
(6)为什么看不到用printk打印的信息?
   a. 打印消息受级别的限制,消息级别可以通过printk设置,如:
        printk("<n>something");  /* 其中0<=n<=7 */
      假设控制台的消息级别为m, 当n<m时消息打印到控制台,否则不打印。
      这样一方面可以提高要打印消息本身的级别(数字越小级别越高),
      另一方面可以改变控制台的消息级别(可从1到8),如改为8可用以下命令:
       # echo "8" > /proc/sys/kernel/printk
   b. 用dmesg命令看。
   c. 当系统运行klogd和syslogd时,内核消息就会由klogd分发到syslogd,
      syslogd会根据配置文件/etc/syslog.conf作相应处理,具体可以查看syslogd
      和syslog.conf的man页。
(7)内核模块开发,对于2.4和2.6版本的内核,差别很大,所以上面介绍对于2.4的开发仅有参考意义

 


Linux 内核模块开发之 Hello world

计算机   2008-11-03 23:39   阅读67   评论0   字号: 大大  中中  小小 Linux 内核模块开发之 Hello world。注意,这里重在演示最简单的模块程序结构以及开发流程,关于详细原理可参考相关书籍资料。

1. hello world 模块 源码

/***************************************************************************
    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, cruel world/n");
}

module_init(hello_init);

module_exit(hello_exit);


2. 编写Makefile

# Makefile
obj-m := hello.o

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

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

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


运行make, 得到hello.ko的文件,即为最终可被内核加载的二进制模块文件。
如果模块是由多个源文件组成的,在Makefile中添加:hello-objs := file_a.o file_b.o


3. 其他:
加载模块: insmod ./hello.ko
卸载模块: rmmod ./hello.ko
查看模块: lsmod | grep hello
查看模块更多信息:modinfo hello
查看模块输出: dmesg

平台:
Linux 2.6.23, GCC 4.1.2 通过。

我的第一个linux程序,动态加载模块HELLO WORD!
 
我的第一个linux程序,动态加载模块HELLO WORD!
 
 
来源: ChinaUnix博客  日期: 2007.01.01 19:25 (共有0条评论) 我要评论
 

                                                经过一个星期的调试终于调试成功!运行在arm2410开发板上!
以下是源程序:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include
#include
MODULE_LICENSE("GPL");
int init_module(void)
{
printk(“Hello world /n”);
return 0;
}
void cleanup_module(void)
{
printk(“Goodbye world /n”);
}
makefile 文件:
CC=arm-linux-gcc
CFLAG := -Wall -DMODULE -D__KERNEL__ -DDEBUG_PRINTK  -I/usr/local/arm/2.4.18/include/
OBJ=hello
$(OBJ).o:$(OBJ).c 
    $(CC) $(CFLAG) -c $(OBJ).c
install:
    insmod $(OBJ).o
clean:
    rm -f *.o
在调试的时候出现的问题:
编译成功但是在insmod ./hello 时出现如下错误:
/usr/local/arm/2.95.3/arm-linux/lib/crt1.o: In function `_start':
/usr/local/arm/2.95.3/arm-linux/lib/crt1.o(.text+0x2c): undefined reference to `main'
/tmp/cczDKmCJ.o: In function `init_module':
/tmp/cczDKmCJ.o(.text+0x3b8): undefined reference to `devfs_register_chrdev'
/tmp/cczDKmCJ.o: In function `cleanup_module':
/tmp/cczDKmCJ.o(.text+0x3e8): undefined reference to `devfs_unregister_chrdev'
原因是在源程序中没有定义__KERNEL__ 和MODULE。
               
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值