Linux 内核模块开发
2017-04-24 19:51
190 查看
一、模块
1、优点:
1、减小内核的体积
2、灵活性加载/卸载 insmod/rmmod
3、看名知意 led.ko
2、设备分类: 字符设备 块设备 网络设备
3、三个基本要素:
1、入口函数insmod调用
module_init(hello_init);
2、出口函数rmmod调用
module_exit(调用函数名);
3、GPL许可
MODULE_LICENSE("GPL");
4、Makefile 注意编写过程中tab
make modules obj-m
虚拟机 内核目录: /lib/modules/
$(MAKE)-C$(KERNELDIR) M=$(PWD) modules
-C 指定内核目录
M 编译模块所存的路径
Makefile具体写法 :
5、编译模块工具:
sudo insmod hello.ko
dmesg 查看内核级打印信息
sudo dmesg -C 清空内核打印信息
insmod hello.ko 加载格式
rmmod hello卸载格式后面不加.ko
lsmod 查看当前内核所加载所有模块
6、samba服务器没有写权限:
1、sudo chmod -R 777 /home/linux
2、sudo umount /home/linux/.gvfs/
3、rm -rf /home/linux/.gvfs/
二、传参:
module_param(name, type, perm)
参数1:传参名称
参数2: 传参类型 char型指针用charp来表示
参数3: 传参权限 一般设置为0664 最大 0774
符号导出:
EXPORT_SYMBOL(函数名称) 为导出函数
加载时先加载函数声明的模块,再加载调用函数的模块
卸载时先卸载调用函数的模块,再卸载函数声明的模块
modinfo 查看模块详细信息
三、设备文件:
crw--w---- 1 root tty 4, 18 Apr 20 15:11 tty18
brw-rw---- 1 root floppy 2, 0 Apr 20 15:11 fd0
c:char 字符设备
b:block 块设备
4:主设备号 表示哪一类设备
18:次设备号 表示哪一类中的第几个设备
设备号(32bit): 主设备号(高12bit) + 次设备号(低20位)
手动创建设备结点:
mknod 创建结点
mknod /dev/led0 c 500 0
在/dev目录下创建一个主设备为500,次设备号为0的字符设备led0
注册字符设备驱动
register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
参数1:主设备号
参数2:注册设备名称 (cat /proc/devices)
参数3:向上提供的接口
结构体成员赋值
struct file_operations fops = {
};
注销字符设备驱动
static inline void unregister_chrdev(unsigned int major, const char *name)
参数1:主设备号
参数2:名称
自动创建设备结点:
class_create(owner, name)
参数1:所属者
THIS_MODULE
参数2: 名称
device_create(struct class * class, struct device * parent, dev_t devt, void * drvdata, const char * fmt,...)
参数1:class_create的返回值
参数2:父类 一般填NULL
参数3:dev_t 设备号类型 宏MKDEV 计算设备号
参数4: 填NULL
参数5:在dev目录下产生的设备名称
参数6: 可变参数
销毁:
void device_destroy(struct class *class, dev_t devt)
参数1:class_create的返回值
参数2:设备号
class_destroy(struct class *cls)
参数1:class_create的返回值#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
unsigned int major = 0;
struct file_operations fops = {
};
struct class *cls;
struct device *dev = NULL;
//char *name = "hello";
int hello_init(void)
{
printk("hello world---\n");
major =register_chrdev(0, "hello", &fops);
cls = class_create(THIS_MODULE, "chrdev");
dev = device_create(cls, NULL, MKDEV(major,0), NULL, "hello");
if(!dev){
printk("device create failed\n");
return -1;
}
return 0;
}
void hello_exit(void)
{
printk("goodbye world\n");
device_destroy(cls, MKDEV(major,0));
class_destroy(cls);
unregister_chrdev(major, "hello");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
1、优点:
1、减小内核的体积
2、灵活性加载/卸载 insmod/rmmod
3、看名知意 led.ko
2、设备分类: 字符设备 块设备 网络设备
3、三个基本要素:
1、入口函数insmod调用
module_init(hello_init);
2、出口函数rmmod调用
module_exit(调用函数名);
3、GPL许可
MODULE_LICENSE("GPL");
4、Makefile 注意编写过程中tab
make modules obj-m
虚拟机 内核目录: /lib/modules/
$(MAKE)-C$(KERNELDIR) M=$(PWD) modules
-C 指定内核目录
M 编译模块所存的路径
Makefile具体写法 :
KERNELDIR:= /lib/modules/$(shell uname -r)/build PWD:=$(shell pwd) obj-m += hello.o 模块编译生成的.o文件 all: $(MAKE) -C $(KERNELDIR)M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR)M=$(PWD) clean
5、编译模块工具:
sudo insmod hello.ko
dmesg 查看内核级打印信息
sudo dmesg -C 清空内核打印信息
insmod hello.ko 加载格式
rmmod hello卸载格式后面不加.ko
lsmod 查看当前内核所加载所有模块
6、samba服务器没有写权限:
1、sudo chmod -R 777 /home/linux
2、sudo umount /home/linux/.gvfs/
3、rm -rf /home/linux/.gvfs/
二、传参:
module_param(name, type, perm)
参数1:传参名称
参数2: 传参类型 char型指针用charp来表示
参数3: 传参权限 一般设置为0664 最大 0774
module_param(fsname, charp, 0774); sudo insmod hello.ko fsname="linux" module_param_array(name, type, len, 0) 参数1:名称 参数2:类型 参数3:长度 参数4:初始值
符号导出:
EXPORT_SYMBOL(函数名称) 为导出函数
int sum_add(int a, int b){ return a+b; } EXPORT_SYMBOL(sum_add);
加载时先加载函数声明的模块,再加载调用函数的模块
卸载时先卸载调用函数的模块,再卸载函数声明的模块
sudo insmod math.ko//声明部分的模块 sudo insmod hello.ko//调用函数模块
modinfo 查看模块详细信息
三、设备文件:
crw--w---- 1 root tty 4, 18 Apr 20 15:11 tty18
brw-rw---- 1 root floppy 2, 0 Apr 20 15:11 fd0
c:char 字符设备
b:block 块设备
4:主设备号 表示哪一类设备
18:次设备号 表示哪一类中的第几个设备
设备号(32bit): 主设备号(高12bit) + 次设备号(低20位)
手动创建设备结点:
mknod 创建结点
mknod /dev/led0 c 500 0
在/dev目录下创建一个主设备为500,次设备号为0的字符设备led0
注册字符设备驱动
register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
参数1:主设备号
参数2:注册设备名称 (cat /proc/devices)
参数3:向上提供的接口
结构体成员赋值
struct file_operations fops = {
};
注销字符设备驱动
static inline void unregister_chrdev(unsigned int major, const char *name)
参数1:主设备号
参数2:名称
自动创建设备结点:
class_create(owner, name)
参数1:所属者
THIS_MODULE
参数2: 名称
device_create(struct class * class, struct device * parent, dev_t devt, void * drvdata, const char * fmt,...)
参数1:class_create的返回值
参数2:父类 一般填NULL
参数3:dev_t 设备号类型 宏MKDEV 计算设备号
参数4: 填NULL
参数5:在dev目录下产生的设备名称
参数6: 可变参数
销毁:
void device_destroy(struct class *class, dev_t devt)
参数1:class_create的返回值
参数2:设备号
class_destroy(struct class *cls)
参数1:class_create的返回值#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
unsigned int major = 0;
struct file_operations fops = {
};
struct class *cls;
struct device *dev = NULL;
//char *name = "hello";
int hello_init(void)
{
printk("hello world---\n");
major =register_chrdev(0, "hello", &fops);
cls = class_create(THIS_MODULE, "chrdev");
dev = device_create(cls, NULL, MKDEV(major,0), NULL, "hello");
if(!dev){
printk("device create failed\n");
return -1;
}
return 0;
}
void hello_exit(void)
{
printk("goodbye world\n");
device_destroy(cls, MKDEV(major,0));
class_destroy(cls);
unregister_chrdev(major, "hello");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
相关文章推荐
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程
- linux 内核模块的编译(用于驱动开发)
- Linux-内核模块开发
- Linux 驱动开发之内核模块开发(四)—— 符号表的导出
- Linux2.6下开发简单的可加载内核模块
- linux驱动开发--内核模块参数
- Linux 驱动开发之内核模块开发 (一)—— 内核模块机制基础
- 【Linux开发】内核模块简介
- 有关 Linux 下内核模块的开发方式的记录
- Linux设备驱动开发详解-Note(7)---Linux 内核模块(1)
- UBuntu8.10 开发第一个基本Linux 驱动内核模块
- Linux 驱动开发之内核模块开发 (二)—— 内核模块编译 Makefile 入门
- Linux操作系统下 内核模块开发详细解析
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程(转)
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程
- Linux 下内核模块的开发方式的记录 及问题解决(入门的Helloworld)
- linux 内核模块开发注意事项
- Linux 驱动开发-0、内核模块设计
- Linux 驱动开发之内核模块开发 (三)—— 模块传参