Linux内核模块开发实例学习

来源:互联网 发布:手机添加网络添加不上 编辑:程序博客网 时间:2024/06/06 17:25

 注:以下程序只是在我机器上测试通过,但代码不一定合理或高效,只是想了解一下内核模块的开发流程,以及工作流程

例子来源于网络,在此表示感谢

[cpp] view plain copy
  1. [root@localhost module]# cat /proc/version   
  2. Linux version 2.6.18-194.el5xen (mockbuild@builder16.centos.org) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-48)) #1 SMP Fri Apr 2 16:16:54 EDT 2010  


1、编写最简单的helloworld版本的内核模块

[cpp] view plain copy
  1. [root@localhost module]# cat hello.c   
  2. #ifndef _KERNEL_  
  3.         #define _KERNEL_  
  4. #endif  
  5.   
  6. #ifndef MODULE  
  7.         #define MODULE  
  8. #endif  
  9.   
  10.   
  11. #include <linux/config.h>  
  12. #include <linux/module.h>  
  13. #include <linux/kernel.h>  
  14.   
  15. static int hello_init(void)  
  16. {  
  17.         printk(KERN_ALERT "hello, I am Tuotuo\n");  
  18.         return 0;  
  19. }  
  20.   
  21. static void hello_exit(void)  
  22. {  
  23.         printk(KERN_ALERT "googbye Kernel mymodule n");  
  24. }  
  25.   
  26. module_init(hello_init);  
  27. module_exit(hello_exit);  


Makefile文件为

[cpp] view plain copy
  1. [root@localhost module]# cat Makefile   
  2. obj-m:=hello.o   
  3. VERSION_NUM:=$(shell uname -r)  
  4. KERNELBUILD := /lib/modules/`uname -r`/build  
  5. CURRENT_PATH:=$(shell pwd)  
  6.   
  7. all:  
  8.         make -C $(KERNELBUILD) M=$(CURRENT_PATH) modules  
  9.   
  10. clean:  
  11.         make -C $(KERNELBUILD) M=$(CURRENT_PATH) clean  

编译

make

加载模块

insmod hello.ko

卸载模块

[cpp] view plain copy
  1. rmmod hello.ko   

查看加载和卸载信息

dmesg

2、学习调用模块

学习http://blog.csdn.net/firststp/article/details/395009

内核模块代码

[cpp] view plain copy
  1. [root@localhost module]# cat TestModule.c   
  2. #ifndef _KERNEL_  
  3.         #define _KERNEL_  
  4. #endif  
  5.   
  6. #ifndef MODULE  
  7.         #define MODULE  
  8. #endif  
  9.   
  10.   
  11. #include <linux/config.h>  
  12. #include <linux/module.h>  
  13. #include <linux/kernel.h>  
  14. #include <linux/version.h>  
  15. #include <linux/types.h>  
  16. #include <linux/fs.h>  
  17. #include <linux/mm.h>  
  18. #include <linux/errno.h>  
  19. #include <asm/segment.h>  
  20. #include <linux/sched.h>  
  21. #include <asm/uaccess.h>  
  22. #include <linux/utsrelease.h>  
  23.   
  24. #define DATA_LENGTH 10  
  25.   
  26. MODULE_LICENSE("GPL");  
  27. MODULE_AUTHOR("TUO LI HENG");  
  28.   
  29. char kernel_version[] = UTS_RELEASE;  
  30.   
  31. unsigned int test_major = 0;  
  32.   
  33. ssize_t read_test(struct file *file, char * buf, size_t count, loff_t *f_ops)  
  34. {  
  35.         int left, i, *p;  
  36.         int data[DATA_LENGTH];  
  37.         p = data;  
  38.         for(i=0; i<10; ++i)  
  39.                 data[i] = 61;  
  40.   
  41.         for(left=count; left>0; --left)  
  42.         {  
  43.                 copy_to_user(buf, p, 1);  
  44.                 ++buf;  
  45.                 ++p;  
  46.         }  
  47.         return 0;  
  48.   
  49. }  
  50.   
  51. ssize_t write_test(struct file *file, char * buf, size_t count, loff_t *f_ops)  
  52. {  
  53.   
  54.         return 0;  
  55. }  
  56.   
  57. static int open_test(struct inode* inode, struct file *file)  
  58. {  
  59.         //      MOD_INC_USE_COUNT;  
  60.         return 0;  
  61.   
  62. }  
  63.   
  64. static int release_test(struct inode *inode, struct file *file)  
  65. {  
  66.         //      MOD_DEC_USE_COUNT;  
  67.         return 0;  
  68. }  
  69.   
  70. struct file_operations test_fops = {  
  71. read: read_test,  
  72. write: write_test,  
  73. open: open_test,  
  74. release: release_test  
  75.   
  76. };  
  77.   
  78.   
  79. static int hello_init(void)  
  80. {  
  81.         printk(KERN_ALERT "hello, I am Tuotuo\n");  
  82.         int result = 0;  
  83.         result = register_chrdev (0, "test", &test_fops);  
  84.         if(result < 0)  
  85.         {  
  86.                 printk(KERN_ALERT "test:can't get major number\n");  
  87.                 return result;  
  88.         }  
  89.         if(test_major == 0)  
  90.                 test_major = result;  
  91.         printk(KERN_ALERT "test major:%d/r/n", result);  
  92.         return 0;  
  93. }  
  94.   
  95.   
  96. static void hello_exit(void)  
  97. {  
  98.         unregister_chrdev(test_major, "test");  
  99.         printk(KERN_ALERT "googbye Kernel module tuotuo\n");  
  100. }  
  101.   
  102. module_init(hello_init);  
  103. module_exit(hello_exit);  


在以上的Makefile里第一行修改为:

[cpp] view plain copy
  1. obj-m:=TestModule.o  


同样

[html] view plain copy
  1. make  
  2.   
  3. insmod TestModule.ko  
  4.   
  5. dmesg  


测试前,先看看是否已经建立了设备文件。 检查 /dev下是否有test设备文件,如果没有,那我们就手工建立一个。用前面看到的主设备号,使用命令: “mknod test c 268 0”  --引用博文


编写调用程序

[html] view plain copy
  1. [root@localhost module]# cat TestApp.c   
  2. #include <stdio.h>  
  3. #include <sys/stat.h>  
  4. #include <fcntl.h>  
  5. int main()  
  6. {  
  7.         char buf[20] = {0,};  
  8.         int i = 0;  
  9.         int p = open("/dev/test", O_RDWR);  
  10.         if(p == -1)  
  11.         {  
  12.                 printf("cannot open\n");  
  13.                 exit(0);  
  14.         }  
  15.         printf("buf addr %ui\r\n",buf);  
  16.         read(p, buf, 10);  
  17.         for(i = 0; i<10; i++)  
  18.         {  
  19.                 printf("%s\r\n",buf+i);  
  20.         }  
  21.         close(p);  
  22.         return 1;  
  23. }  


编译

[html] view plain copy
  1. gcc TestApp.c -o TestApp  


运行

[cpp] view plain copy
  1. [root@localhost module]# ./TestApp   
  2. buf addr 3218386872i  
  3. ==========  
  4. =========  
  5. ========  
  6. =======  
  7. ======  
  8. =====  
  9. ====  
  10. ===  
  11. ==  
  12. =  
原创粉丝点击