Linux内核模块开发实例学习
来源:互联网 发布:手机添加网络添加不上 编辑:程序博客网 时间:2024/06/06 17:25
注:以下程序只是在我机器上测试通过,但代码不一定合理或高效,只是想了解一下内核模块的开发流程,以及工作流程
例子来源于网络,在此表示感谢
- [root@localhost module]# cat /proc/version
- 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版本的内核模块
- [root@localhost module]# cat hello.c
- #ifndef _KERNEL_
- #define _KERNEL_
- #endif
-
- #ifndef MODULE
- #define MODULE
- #endif
-
-
- #include <linux/config.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
-
- static int hello_init(void)
- {
- printk(KERN_ALERT "hello, I am Tuotuo\n");
- return 0;
- }
-
- static void hello_exit(void)
- {
- printk(KERN_ALERT "googbye Kernel mymodule n");
- }
-
- module_init(hello_init);
- module_exit(hello_exit);
Makefile文件为
- [root@localhost module]# cat Makefile
- obj-m:=hello.o
- VERSION_NUM:=$(shell uname -r)
- KERNELBUILD := /lib/modules/`uname -r`/build
- CURRENT_PATH:=$(shell pwd)
-
- all:
- make -C $(KERNELBUILD) M=$(CURRENT_PATH) modules
-
- clean:
- make -C $(KERNELBUILD) M=$(CURRENT_PATH) clean
编译
make
加载模块
insmod hello.ko
卸载模块
查看加载和卸载信息
dmesg
2、学习调用模块
学习http://blog.csdn.net/firststp/article/details/395009
内核模块代码
- [root@localhost module]# cat TestModule.c
- #ifndef _KERNEL_
- #define _KERNEL_
- #endif
-
- #ifndef MODULE
- #define MODULE
- #endif
-
-
- #include <linux/config.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/version.h>
- #include <linux/types.h>
- #include <linux/fs.h>
- #include <linux/mm.h>
- #include <linux/errno.h>
- #include <asm/segment.h>
- #include <linux/sched.h>
- #include <asm/uaccess.h>
- #include <linux/utsrelease.h>
-
- #define DATA_LENGTH 10
-
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("TUO LI HENG");
-
- char kernel_version[] = UTS_RELEASE;
-
- unsigned int test_major = 0;
-
- ssize_t read_test(struct file *file, char * buf, size_t count, loff_t *f_ops)
- {
- int left, i, *p;
- int data[DATA_LENGTH];
- p = data;
- for(i=0; i<10; ++i)
- data[i] = 61;
-
- for(left=count; left>0; --left)
- {
- copy_to_user(buf, p, 1);
- ++buf;
- ++p;
- }
- return 0;
-
- }
-
- ssize_t write_test(struct file *file, char * buf, size_t count, loff_t *f_ops)
- {
-
- return 0;
- }
-
- static int open_test(struct inode* inode, struct file *file)
- {
-
- return 0;
-
- }
-
- static int release_test(struct inode *inode, struct file *file)
- {
-
- return 0;
- }
-
- struct file_operations test_fops = {
- read: read_test,
- write: write_test,
- open: open_test,
- release: release_test
-
- };
-
-
- static int hello_init(void)
- {
- printk(KERN_ALERT "hello, I am Tuotuo\n");
- int result = 0;
- result = register_chrdev (0, "test", &test_fops);
- if(result < 0)
- {
- printk(KERN_ALERT "test:can't get major number\n");
- return result;
- }
- if(test_major == 0)
- test_major = result;
- printk(KERN_ALERT "test major:%d/r/n", result);
- return 0;
- }
-
-
- static void hello_exit(void)
- {
- unregister_chrdev(test_major, "test");
- printk(KERN_ALERT "googbye Kernel module tuotuo\n");
- }
-
- module_init(hello_init);
- module_exit(hello_exit);
在以上的Makefile里第一行修改为:
同样
- make
-
- insmod TestModule.ko
-
- dmesg
测试前,先看看是否已经建立了设备文件。 检查 /dev下是否有test设备文件,如果没有,那我们就手工建立一个。用前面看到的主设备号,使用命令: “mknod test c 268 0” --引用博文
编写调用程序
- [root@localhost module]# cat TestApp.c
- #include <stdio.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int main()
- {
- char buf[20] = {0,};
- int i = 0;
- int p = open("/dev/test", O_RDWR);
- if(p == -1)
- {
- printf("cannot open\n");
- exit(0);
- }
- printf("buf addr %ui\r\n",buf);
- read(p, buf, 10);
- for(i = 0; i<10; i++)
- {
- printf("%s\r\n",buf+i);
- }
- close(p);
- return 1;
- }
编译
运行
- [root@localhost module]# ./TestApp
- buf addr 3218386872i
- ==========
- =========
- ========
- =======
- ======
- =====
- ====
- ===
- ==
- =