Tiny6410内核模块编译之helloworld

        

         由于项目,需要自己编译内核驱动,但是考虑到编译内核比较麻烦,而且需要重新烧写系统,不是很方便,所以研究了一下通过模块的方式加载驱动。用一个 helloworld的程序说明一下整个流程,记下来,以便以后查阅。

编译环境说明:

  • 主机操作系统:ubuntu12.04
  • 编译的linux内核:linux-2.6.38
  • 嵌入式系统:tiny6410

一、编译zImage

        在编译zImage之前,需要一个.config文件,这个文件包含了内核的配置信息,可以通过以下四个命令获得:
  • make config
  • make menuconfig
  • make oldconfig
  • make xconfig
        推荐使用make menuconfig进行配置,因为菜单化配置比较直观。
        不过我在进行配置的时候为了方便,就直接拷贝关盘自带的config文件进行编译。如下图所示:

拷贝config_mini6410_a70 到 .config文件。
cp config_mini6410_a70 .config
当然有了这个.config配置文件以后,自己也可以根据需要修改。
接下来就可以进行zImage的编译了。
make zImage
直到编译完成,需要等一段时间。

二、 什么是模块

        内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个单内核(monolithic kernel)。单内核的最大优点是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。

        模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。

  • 应用程序与内核模块的比较
  C语言应用程序 内核模块程序
使用函数 Libc库 内核函数
运行空间 用户空间 内核空间
运行权限 普通用户 超级用户
入口函数 main() module_init()
出口函数 exit() module_exit()
编译 Gcc –c Makefile
连接 Gcc insmod
运行 直接运行 insmod
调试 Gdb kdbug, kdb,kgdb等
        从表中我们可以看出,内核模块程序不能调用libc库中的函数,它运行在内核空间,且只有超级用户可以对其运行。另外,模块程序必须通过module_init()和module-exit()函数来告诉内核“我来了”和“我走了”。

三、helloworld模块

helloworld_module.c

/* file begin helloworld_module.c */

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

static int __init helloworld_init(void){
	printk(KERN_WARNING"Hello world!\n");
	return 0;
}

static void __exit helloworld_exit(void){
	printk(KERN_INFO"Goodbye world!\n");
}

module_init(helloworld_init);
module_exit(helloworld_exit);
MODULE_LICENSE("Dual BSD/GPL");

/* file end */

第3行:头文件init.h包含了宏_init和_exit,它们允许释放内核占用的内存。

第4行:所有模块都要使用头文件module.h,此文件必须包含进来。

第6-9行:这是模块的初始化函数,它必需包含诸如要编译的代码、初始化数据结构等内容。第7行使用了printk()函数,该函数是由内核定义的,功能与C库中的printf()类似,它把要打印的信息输出到终端或系统日志。字符串中的KERN_WARNING是输出的级别。

第11-13行:这是模块的退出和清理函数。此处可以做所有终止该驱动程序时相关的清理工作。

第15行:这是驱动程序初始化的入口点。对于内置模块,内核在引导时调用该入口点,对可加载模块在该模块插入内核时才调用。

第16行:对于可加载模块,内核在此处调用module_cleanup()函数,而对于内置的模块,它什么都不做。
第17行:提示可能没有GNU公共许可证。

        函数module_init()和module_exit()是模块编程中最基本也是必须的两个函数。module_init()向内核注册模块所提供的新功能,而module_exit()注销由模块提供的所有功能。



Makefile

ifneq ($(KERNELRELEASE),)

obj-m := helloworld_module.o

else

KDIR := /opt/FriendlyARM/tiny6410/linux/linux-2.6.38
PWD := $(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	rm -f *.ko *.o *.mod.c *.symvers *.cmd

endif
        Linux 中最重要的软件开发工具是 GCC。GCC 是 GNU 的 C 和 C++ 编译器。但是,在大型的开发项目中,通常有几十到上百个的源文件,如果每次均手工键入 gcc 命令进行编译的话,则会非常不方便。因此,人们通常利用 make 工具来自动完成编译工作。利用这种自动编译可大大简化开发工作,避免不必要的重新编译。这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。
        执行如下命令,编译生成helloworld_module.ko文件。

make

四、运行helloworld_module模块

        ftp上传helloworld_module.ko到开发板上。


        并把它移动到开发板的/lib/modules/2.6.38-FriendlyARM目录。


        加载和卸载模块。



补充:

modutils是管理内核模块的一个软件包。可以在任何获得内核源代码的地方获取Modutils(modutils-x.y.z.tar.gz)源代码,然后选择最高级别的patch.x.y.z等于或小于当前的内核版本,安装后在/sbin目录下就会有insomod、rmmod、ksyms、lsmod、modprobe等实用程序。当然,通常我们在加载Linux内核时,modutils已经被载入。

1.Insmod命令
调用insmod程序把需要插入的模块以目标代码的形式插入到内核中。在插入的时候,insmod自动调用init_module()函数运行。注意,只有超级用户才能使用这个命令,其命令格式为:
# insmod [path] modulename.c

2. rmmod命令
调用rmmod程序将已经插入内核的模块从内核中移出,rmmod会自动运行cleanup_module()函数,其命令格式为:
#rmmod [path] modulename.c

3.lsmod命令
调用lsmod程序将显示当前系统中正在使用的模块信息。实际上这个程序的功能就是读取/proc文件系统中的文件/proc/modules中的信息,其命令格式为:
#lsmod

4.ksyms命令
ksyms这个程序用来显示内核符号和模块符号表的信息。与lsmod相似,它的功能是读取/proc文件系统中的另一个文件/proc/kallsyms。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值