您的位置:首页 > 其它

hello world及内核模块 && MTK平台添加kernel module && 生成.ko的驱动改生成.o

2009-11-29 00:07 1181 查看
(1)用户程序,实例

启动终端,首先用VI编写一个C程序:vi hello.c

#include  <stdio.h>
int main()
{
         printf("hello world!!!/n");
         return 0;
}

接着用GCC进行编译:gcc -o hello hello.c生成hello,最后运行该程序:./hello,在终端上你会看到:hello world!!!

上面是在操作系统基础上进行的用户应用程序的开发。然而对于linux驱动程序的开发是绝然不同的,因为驱动程序的开发是运行在内核空间的,而应用程序是运行在用户空间的。也就是说,程序不能直接通过指针,把用户空间的数据地址传递给内核。要想在应用程序和驱动程序之间传递数据(指针),就需要经过转换。把用户态“看到”的空间地址转换成内核态可访问的地址。

Linux内核把驱动程序划分为3种类型:字符设备、块设备和网络设备。应用程序对于字符设备的每一个I/O操作,都会直接传递给系统内核对应的驱动程序;而应用程序对于块设备的操作,要经过系统的缓冲区管理,间接传递给驱动程序处理。块设备的这种管理方式是为存储提供优化的;而字符设备的管理方式是为操作提供优化的。

(2) 内核程序,驱动模块实例

在linux系统中,驱动程序都做成模块的形式,也就是module。简单的说,一个模块提供一个功能,这些模块是可以按照需要随时装入内核空间和从内核空间卸载的。因此,内核模块是为了给内核动态增减功能而设计的,并不仅仅是限于驱动程序。当用户输入命令“insmod 模块文件名”加载内核模块时,系统会检测此模块能否被加载,如果能被加载,内核调用模块的初始化函数module_init()(2.4内核为init_module())。当用户输入命令“rmmod 模块文件名”卸载内核模块时,此时,系统会检测此模块是否能被卸载,内核将调用模块清除函数module_exit()(2.4内核为cleanup_module())。

内核模块驱动以my.c实例来说明,它没有main函数:

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

static void __exit accel_sens_exit(void)
{
	printk("module out kernel_test_exit \r\n");
}

static int __init accel_sens_init(void)
{
		printk("module in kernel_test_init \r\n");
		return 0;
}

module_init(accel_sens_init);
module_exit(accel_sens_exit);
MODULE_DESCRIPTION("QL_ULPSH Accel  driver");
MODULE_AUTHOR("QuickLogic Inc");
MODULE_LICENSE("GPL v2");

另外,编写一个Makefile,如下:

obj-m:=my.o
KDIR:=/lib/modules/$(shell uname -r)/build
MAKE:=make
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

以上经过验证。执行make即可编译,生成若干项文件。注意,如果执行时提示Nothing to be done for `modules',则是形如$(MAKE) -C $(KERNELDIR) M=$(PWD) modules的make命令之前要有一个Tab键,而不是空格。

在ubuntu终端中执行加载一下insmod my.ko dmesg|grep module 看到模块初始化时候的打印(用lsmod也可以看模块),卸载模块rmmod my dmesg|grep module 看模块卸载时候的打印。正确结果如下:



在PC机上提示ERROR: Removing 'my': Device or resource busy,可能原因是Ubuntu的内核选项默认没有勾上Module unloading。这样的话,我们可以在嵌入式平台上做这个实验,需要注意的是编译器也要是交叉编译器,且实验的目标板系统与编译器版本要一致。

比如在MTK上手机平台代码中放置这个实验代码,PC.MK中添加目录,makefile直接用

# Each configuration option enables a list of files.
obj-m							+= helloworld.o
让文件和内核一起编译,再将生成的ko push到机子的system/bin。执行insmod helloworld.ko,用dmesg即可看到对应的Log。用lsmod可确认已加载的模块信息



再执行rmmod helloworld,即可查看退出信息。



=====================================================================================

至于如何在MTK平台添加kernel module,可参见FAQ07275。

=====================================================================================

调试驱动时碰到一个现象:要在A.o的驱动中调用B.ko的驱动中的变量c,结果编译都编不过,提示C没有定义。究其原因,在编译状态,B驱动中的C变量对A来说,是不存在的,所以才会有这个提示。

如何解决?把B.ko也改成生成.o,这样AB就能互相访问了。把B驱动中的makefile的obj-m换成obj-y即可,编译开机会提示在某驱动注册异常导致不停重启。修改makefile,使先加载的o放在后加载o的前面即可解决。

参考原文:http://blog.csdn.net/sabalol/article/details/2076610

参考原文:http://blank-dic.blog.163.com/blog/static/310186222011221112425351/

参考原文:http://hi.baidu.com/serial_story/blog/item/90c81734e58009335ab5f562.html

参考原文:http://blog.csdn.net/elfylin/article/details/5908265
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: