hello world及内核模块 && MTK平台添加kernel module && 生成.ko的驱动改生成.o
2009-11-29 00:07
1181 查看
(1)用户程序,实例
启动终端,首先用VI编写一个C程序:vi hello.c
接着用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函数:
另外,编写一个Makefile,如下:
以上经过验证。执行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 看模块卸载时候的打印。正确结果如下:
![](http://img.blog.csdn.net/20150811144528559)
在PC机上提示ERROR: Removing 'my': Device or resource busy,可能原因是Ubuntu的内核选项默认没有勾上Module unloading。这样的话,我们可以在嵌入式平台上做这个实验,需要注意的是编译器也要是交叉编译器,且实验的目标板系统与编译器版本要一致。
比如在MTK上手机平台代码中放置这个实验代码,PC.MK中添加目录,makefile直接用
![](http://img.blog.csdn.net/20150801084623351)
再执行rmmod helloworld,即可查看退出信息。
![](http://img.blog.csdn.net/20150801084907608)
=====================================================================================
至于如何在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
启动终端,首先用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
相关文章推荐
- 如何把rtl8188EUS驱动编译生成ko模块并且下载到rk平台Android4.2.2上使用
- Android 中用内核模块实现系统调用(Implement system call by kernel module in Android)
- 基于linux-2.6.38.8内核的SDIO/wifi驱动分析&&android 平台USB wifi驱动移植及使用 SDIOwifi
- linux 内核学习----------模块(LKM:loading kernel module)
- Linux升级内核& 添加驱动
- [Kernel] Linux 4.10.0+ 下编译安装内核模块(Hello World为例)
- ok6410开发板android底层驱动模块编写,出现insmod:init_module ‘hello.ko’ failed (Exec format error)
- MTK平台Sensor驱动添加
- 嵌入式 对于Linux下驱动module_param&&MODULE_PARM_DESC模块参数详解
- AllWinnerTech A10添加驱动ko模块方法
- 基于S3C2410平台移植Linux 2.6.14内核&驱动指南
- AllWinnerTech A10添加驱动ko模块方法
- Android平台添加外设的架构流程(kernel->HAL->JNI->API->APP)之学习提高篇
- 通过GDB调试内核(Kernel)和模块(Module)
- linux 编译进内核 && 编译成模块module
- 为Android内核添加hello world驱动并添加到menuconfig菜单
- AllWinnerTech A10添加驱动ko模块方法
- 添加内核模块之入门helloworld.ko
- 如何把一个自己写的外部驱动模块编译添加到内核中 来自网络
- ZLG I.MX287A led内核驱动模块调试生成记录