您的位置:首页 > 运维架构 > Linux

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具体写法  :
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");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: