字符设备(三)-----杂项设备

 前言

    前面字符设备(一)-----驱动结构   字符设备(二)-----驱动模型 已经对字符设备有了一定的了解,下面看下杂项设备。杂项设备是一种特殊的字符设备,是对字符设备的一种封装。相比字符设备杂项设备有如下优势:

        a、节省主设备号:杂项设备的主设备号固定为 10,而字符设备不管是动态分配还是静态分配设备号,都会消耗一个主设备号,进而造成了主设备号浪费。当系统中注册了多个 misc 备驱动时,只需使用子设备号进行区分即可。

        b、更加简单:杂项设备不需要进行复杂字符设备注册和class_create、和device_create等操作来创建设备节点,而只需要将基本信息通过结构体传递给相应处理函数即可。

在字符设备中使用cdev 结构体来描述一个设备,而在杂项设备中也有同样描述杂项设备的结构体 struct miscdevice,定义一个misc设备,一般只需要填充minor、name、fops这三个成员变量。

struct miscdevice {
    int minor; /* 子设备号 需要用户填写*/
    const char *name;/* 设备名 需要用户填写*/
    const struct file_operations *fops;/* 设备操作集 需要用户填写*/
    struct list_head list;
    struct device *parent;
    struct device *this_device;
    const struct attribute_group **groups;
    const char *nodename;
    umode_t mode;
};

        minor次设备号可以手动在/include/linux/miscdevice.h 中预定的次设备号挑选,也可以自行设置没有被使用的设备号。通常情况下将该参数设置为MISC_DYNAMIC_MINOR,表示自动分配子设备号。

        name 表示 misc 设备的名字。misc 设备驱动注册成功之后,会在 dev 目录下生成名为name 的设备节点。

        fops 指向了 file_operations 的结构体,表示字符设备的操作集合。(像字符设备中的操作集合一样填充对应read、write等)

一、杂项设备注册

        杂项设备的注册可以直接通过 misc_register来进行注册。
int misc_register(struct miscdevice *misc)

二、 杂项设备卸载

        杂项设备的卸载可以通过misc_deregister函数完成,非常的简单方便。

int misc_deregister(struct miscdevice *misc)

三、实验代码

misc.c
#include <linux/init.h> //初始化头文件
#include <linux/module.h> //最基本的文件,支持动态添加和卸载模块。
#include <linux/miscdevice.h> //注册杂项设备头文件
#include <linux/fs.h> //注册设备节点的文件结构体



static int misc_open(struct inode *inode, struct file *file)
{
    printk("This is misc_open -\n");
    return 0;
}
static ssize_t misc_read(struct file *file,char __user *buf, size_t size, loff_t *off)
{
    printk("This is misc_read -\n");
    return 0;
}
static ssize_t misc_write(struct file *file,const char __user *buf,size_t size,loff_t                 *off)
{
    printk("This is misc_write- \n");
    return 0;
}
static int misc_release(struct inode *inode, struct file *file)
{
    
    printk("This is misc_release- \n");
    return 0;
}


struct file_operations misc_fops = { //文件操作集
    .owner = THIS_MODULE, 将 owner 字段指向本模块,可以避免在模块的操作正在被使用时卸载该模
    .open = misc_open, //将 open 字段指向 misc_open(...)函数
    .read = misc_read, //将 open 字段指向 misc_read(...)函数
    .write = misc_write,//将 open 字段指向 misc_write(...)函数
    .release = misc_release,//将 open 字段指向 misc_release(...)函数
};
struct miscdevice misc_dev = { //杂项设备结构体
    .minor = MISC_DYNAMIC_MINOR, //动态申请的次设备号
    .name = "test", //杂项设备名字是 hello_misc
    .fops = &misc_fops, //文件操作集
};
static int __init misc_init(void)
{
    int ret;
    ret = misc_register(&misc_dev); //在初始化函数中注册杂项设备
    if (ret < 0)
    {
    printk("misc registe is error \n"); //打印注册杂项设备失败
    }
    printk("misc registe is succeed \n");//打印注册杂项设备成功
    return 0;
}
static void __exit misc_exit(void)
{
    misc_deregister(&misc_dev); //在卸载函数中注销杂项设备
    printk(" misc goodbye! \n");
}
module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ll");

app.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc,char *argv[])
{
	int fd;//定义 int 类型的文件描述符
	char buf[32];//定义读取缓冲区 buf
	fd=open(argv[1],O_RDWR,0666);//调用 open 函数,打开输入的第一个参数文件,权限为可读可写
	if(fd<0){
	    printf("open is error\n");
	    return -1;
    }
	printf("open is ok\n");

	if(!strcmp(argv[2], "read")){
		read(fd,buf,32);

	}
	else if(!strcmp(argv[2], "write")){
		write(fd,"hello\n",6);
	}
	close(fd);//调用 close 函数,对取消文件描述符到文件的映射
	return 0;
}

Makefile

export ARCH=arm64
export CC=/home/ljw/work/project/rk3568/rk356x_linux/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc

DEV:=misc
obj-m += $(DEV).o #xxx.c 对应.o 文件的名称。名称要保持一致。
APP:=app
KDIR :=/home/ljw/work/project/rk3568/rk356x_linux/kernel #内核源码所在虚拟机 ubuntu 的实际路径
PWD ?= $(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules #make 操作 
	$(CC) $(APP).c -o $(APP)
	cp  *.ko $(APP) /mnt/hgfs/share/$(DEV)

dir:
	mkdir /mnt/hgfs/share/$(DEV)

app:
	$(CC) $(APP).c -o $(APP)

cp:
	cp  *.ko $(APP) /mnt/hgfs/share/


clean:
	make -C $(KDIR) M=$(PWD) clean
	rm $(APP)

四、运行测试

insmod misc.ko
因为杂项设备的主设备号都是10,所以使用cat /proc/devices 下看不出来刚刚注册的设备,可以进入 /sys/class/misc 中找到对应的杂项设备。
可以看到杂项设备test 的主设备号是10,次设备号是53 ,并且在生成 /dev/test在后面测试中就可以直接打开/dev/test 来操作杂项设备。
app测试
./app /dev/test read

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值