模块编程
Linux驱动本质上是一种模块,模块要实现相应的接口,这样和Linux内核这个主体结合。但凡模块的编程模式大都相似,如PHP模块,nginx模块等。
模块编程主要关注以下几点:
- 主体怎么知道模块加进来了
- 模块要实现哪些接口,以为主体所用
- 模块可以调用主体的哪些接口
先睹为快
还是先看一个例子。
word_count.c :
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "wordcount"
static ssize_t word_count_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
// 业务逻辑
return 0;
}
static ssize_t word_count_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
// 业务逻辑
return 0;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.read = word_count_read,
.write = word_count_write
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops
};
static int word_count_init(void) {
int ret;
// 创建设备文件
ret = misc_register(&misc);
printk("word_count_init_success\n");
return 0;
}
static void word_count_exit(void) {
// 注销设备文件
misc_deregister(&misc);
printk("word_count_exit_sucess\n");
}
// register init function
module_init(word_count_init)
// register exit function
module_exit(word_count_exit)
// 驱动信息 modinfo
MODULE_AUTHOR("lijianxing");
MODULE_DESCRIPTION("statistics of word count");
MODULE_ALIAS("word count module.");
MODULE_LICENSE("GPL");
Makefile:
obj-m := word_count.o
编译:
make -C /usr/src/linux-headers-3.16.0-30-generic/ M=your_path/word_count
安装驱动:
sudo insmod word_count.ko
卸载驱动:
sudo rmmod word_count
使用dmsg命令可以可以查看printk输出的信息:
dmesg | grep word_count
可以看到如下输出:
[38281.439946] word_count_init_success
[38427.487553] word_count_exit_sucess
示例分析
Linux内核怎么模块加载进来了?
我们知道Linux模块是可以动态加载的,上述的insmod和rmmod命令就是干这事。模块可以使用Linux内核的哪些接口?
Linux模块本身就加载到内核空间运行,可以看作是内核代码的一部分。模块要实现哪些接口?
在代码中还有一个宏module_init,该宏指定了我们模块的初始化函数word_count_init。在word_count_init中,调用 misc_register 调用misc_deregister 注册了一个misc设备。这里面涉及了比较多的细节,先放放吧,后面再分析了。