hello world及内核模块 && 生成.ko的驱动改生成.o
来源:互联网 发布:国际认证大数据证书 编辑:程序博客网 时间:2024/06/07 22:58
(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.oKDIR:=/lib/modules/$(shell uname -r)/buildMAKE:=makedefault:$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modulesclean:$(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,即可查看退出信息。
(3)对于内核模块,我们会见到很多种申明,有什么差别呢?
#define pure_initcall(fn) __define_initcall("0",fn,1)#define core_initcall(fn) __define_initcall("1",fn,1)#define core_initcall_sync(fn) __define_initcall("1s",fn,1s)#define postcore_initcall(fn) __define_initcall("2",fn,2)#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)#define arch_initcall(fn) __define_initcall("3",fn,3)#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)#define subsys_initcall(fn) __define_initcall("4",fn,4)#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)#define fs_initcall(fn) __define_initcall("5",fn,5)#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)#define device_initcall(fn) __define_initcall("6",fn,6)#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)#define late_initcall(fn) __define_initcall("7",fn,7)#define late_initcall_sync(fn) __define_initcall("7s",fn,7s)#define module_init(x) __initcall(x);#define __initcall(fn) device_initcall(fn)值越小,越早调用。所以module_init还在late_initcall前面调用
====================================生成.ko的驱动改生成.o==================================
调试驱动时碰到一个现象:要在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
- hello world及内核模块 && 生成.ko的驱动改生成.o
- Linux内核驱动模块测试 hello.ko
- Linux内核驱动模块编写(Hello,World)
- Linux内核驱动模块编写(Hello,World)
- 内核模块的hello world!
- Linux .ko模块的生成方式
- Linux下hello.ko内核模块制作的全过程
- Linux下hello.ko内核模块制作的全过程
- Linux下hello.ko内核模块制作的全过程
- linux内核驱动模块编程框架---(hello world模块)
- hello world 内核模块
- 多个*.c文件编译生成一个模块驱动*.ko的makefile文件编写
- hello world!(驱动模块)
- Hellomod , Linux内核模块的Hello World
- 第一个内核模块Hello.ko代码
- Linux2.4内核驱动的Hello World
- linux内核模块编程----ubuntu下我的第一个Hello World驱动
- 内核模块编程---hello world
- 专门的考试学习培训课程录象资料bt下载
- 《java核心技术》——对象与类-笔记
- 智能手机软件平台 Android VS iPhone OS: 软件商店 (4/4)
- disable the alterabyteblaster service with command
- 3种Timer的用法
- hello world及内核模块 && 生成.ko的驱动改生成.o
- t-sql日期函数小技巧
- Oracle SQL与PL/SQL学习笔记(-)
- Is the Quartus® II software compatible with Microsoft Windows XP SP2
- spring aop
- 【视频】配置信息管理 的 使用方法(六):实现添加、修改、查询
- 检索 COM 类工厂中 CLSID 为{00024500-0000-0000-C000-000000000046} 的组件时失败——解决方法
- 2009-11-28
- 忆龙2009:XP客户端通过IP Phone连接CISCO交换机,为何无法完成认证?