当前位置:   article > 正文

hello world及内核模块 && 把.ko的驱动改生成.o的场景_ubuntu .o与.ko

ubuntu .o与.ko

(1)用户程序,实例

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

  1. #include <stdio.h>
  2. int main()
  3. {
  4. printf("hello world!!!/n");
  5. return 0;
  6. }

       接着用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函数:

  1. #include <linux/init.h>
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>
  4. #include <linux/jiffies.h>
  5. #include <linux/timer.h>
  6. static void __exit accel_sens_exit(void)
  7. {
  8. printk("module out kernel_test_exit \r\n");
  9. }
  10. static int __init accel_sens_init(void)
  11. {
  12. printk("module in kernel_test_init \r\n");
  13. return 0;
  14. }
  15. module_init(accel_sens_init);
  16. module_exit(accel_sens_exit);
  17. MODULE_DESCRIPTION("QL_ULPSH Accel driver");
  18. MODULE_AUTHOR("QuickLogic Inc");
  19. MODULE_LICENSE("GPL v2");

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

  1. obj-m:=my.o
  2. KDIR:=/lib/modules/$(shell uname -r)/build
  3. MAKE:=make
  4. default:
  5. $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
  6. clean:
  7. $(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直接用

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

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


(3)对于内核模块,我们会见到很多种申明,有什么差别呢?

  1. #define pure_initcall(fn) __define_initcall("0",fn,1)
  2. #define core_initcall(fn) __define_initcall("1",fn,1)
  3. #define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
  4. #define postcore_initcall(fn) __define_initcall("2",fn,2)
  5. #define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
  6. #define arch_initcall(fn) __define_initcall("3",fn,3)
  7. #define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)
  8. #define subsys_initcall(fn) __define_initcall("4",fn,4)
  9. #define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
  10. #define fs_initcall(fn) __define_initcall("5",fn,5)
  11. #define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
  12. #define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
  13. #define device_initcall(fn) __define_initcall("6",fn,6)
  14. #define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
  15. #define late_initcall(fn) __define_initcall("7",fn,7)
  16. #define late_initcall_sync(fn) __define_initcall("7s",fn,7s)
  17. #define module_init(x) __initcall(x);
  18. #define __initcall(fn) device_initcall(fn)
值越小,越早调用。所以module_init还在late_initcall前面调用

==================把.ko的驱动改生成.o的场景=======================

       调试驱动时碰到一个现象:要在A.o的驱动中调用B.ko的驱动中的变量c,结果编译都编不过,提示C没有定义。究其原因,ko文件是内核运行后且insmod之后,才正式加载;B驱动中的C变量对A来说,并不是一定存在的(比如仅编译而不加载这个ko),所以才会有这个提示。

       如何解决?把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 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/246852?site
推荐阅读
相关标签
  

闽ICP备14008679号