• LINUX字符型设备驱动 二.自动创建设备节点


    1.利用mdev来实现设备文件的自动创建

    因为我的文件系统是基于buildroot的,并且已经配置了mdev。

    所以在驱动初始化代码中调用class_create(),为该设备创建一个class,再调用device_create()创建对应的设备。

    内核中定义了struct class 结构体,这个类是一个设备高层抽象的属性,隐藏了底层具体实现过程。

    2.实例

    hello.c

    #include <linux/module.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <linux/device.h>
    static int major = 99; //主设备号(用于区分设备类)
    static int minor = 0;  //次设备号(用于区分哪个设备)
    
    static dev_t devno;
    static struct class *hello_class;
    static struct device *hello_device;
    
    static int hello_open(struct inode *inodep, struct file *filep)
    {
        printk(KERN_ALERT "hello are opened 
    ");
        return 0;
    }
    //通过file_operations 对应open、close、sleek等文件操作
    static struct file_operations hello_ops = {
        .open = hello_open,
    };
    
    static int hello_init(void)
    {
        int ret;
        printk(KERN_ALERT "hello_init
    ");
        //第一步:将主设备号、次设备号转化成dev_t类型
        devno = MKDEV(major, minor);
        //注册字符设备:在/porc/devices中可以查看设备号
        ret = register_chrdev(major, "hello", &hello_ops);
        if (ret < 0)
        {
            printk(KERN_ERR "my register_chrdev fail 
    ");
            return ret;
        }
        printk(KERN_INFO "register_chrdev_region success
    ");
    
        //第二步:创建设备类,注册字符设备!
        hello_class = class_create(THIS_MODULE, "myclass");//将在/sys/class/下创建maclass文件夹
        if (IS_ERR(hello_class))
        {
            unregister_chrdev(major, "hello");
            printk(KERN_ERR "class create failed
    ");
            return -EBUSY;
        }
        printk(KERN_INFO "class create success
    ");
        //第三步:2.6内核之后要向sys文件系统中添加设备
        hello_device=device_create(hello_class,NULL,devno,NULL,"hello");//此处将在/dev下创建hello设备!
        if (IS_ERR(hello_device))
        {
            class_destroy(hello_class);
            unregister_chrdev(major,"hello");
            printk(KERN_ERR "Uable to add dev
    ");
            return -EBUSY;
        }
        printk(KERN_INFO "cdev_add success
    ");
    
        return 0;
    }
    static void hello_exit(void)
    {
        //先删除设备,再删除类
        device_destroy(hello_class,devno);
        class_destroy(hello_class);
        unregister_chrdev(major,"hello"); //注销设备号
        printk(KERN_ALERT "hell_exit
    ");
    }
    MODULE_LICENSE("GPL");
    module_init(hello_init);
    module_exit(hello_exit);

    test.c

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    main()
    {
        int fd;
    
        fd = open("/dev/hello",O_RDWR);
        if(fd<0)
        {
            perror("open fail 
    ");
            return ;
        }else
        {
            printf("open /dev/hello success! 
    ");
        }
    
        close(fd);
    }

    makefile

    #General Purpose Makefile for cross compile Linux Kernel module
    ifneq ($(KERNELRELEASE),)
    obj-m := hello.o  #+=是连接字符串
    else
    
    ARCH := arm    
    CROSS_COMPILE := arm-linux-gnueabihf-
    KERN_DIR := /home/zqh/lichee/linux-zero-4.14.y  #选择内核路径
    PWD :=$(shell pwd)   #当前路径
    
    all:
            $(info "1st")
            make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) modules    
    clean:                                   
            rm -f *.ko *.o *.symvers *.mod.c *.mod.o *.order .*.o.ko.cmd .*.ko.cmd .*.mod.o.cmd .*.o.cmd
            
    endif
     

    3.现象

    # insmod  hello.ko 
    # dmesg | tail -20
    [    2.196495] RTL8723BS: rtl8723bs BT-Coex version = BTCOEX20140507-4E40
    [    2.204039] pnetdev = c327f800
    [    2.241016] RTL8723BS: rtw_ndev_init(wlan0)
    [    2.247054] RTL8723BS: module init ret =0
    [    2.259012] rtl8723bs: acquire FW from file:rtlwifi/rtl8723bs_nic.bin
    [    2.503466] random: crng init done
    [    5.493474] RTL8723BS: rtw_set_802_11_connect(wlan0)  fw_state = 0x00000008
    [    5.802276] RTL8723BS: start auth
    [    5.806943] RTL8723BS: auth success, start assoc
    [    5.813025] RTL8723BS: rtw_cfg80211_indicate_connect(wlan0) BSS not found !!
    [    5.820189] RTL8723BS: assoc success
    [    5.829687] RTL8723BS: send eapol packet
    [    5.840116] RTL8723BS: send eapol packet
    [    5.844757] RTL8723BS: set pairwise key camid:4, addr:e6:02:9b:c8:c8:41, kid:0, type:AES
    [    5.855579] RTL8723BS: set group key camid:5, addr:e6:02:9b:c8:c8:41, kid:2, type:AES
    [   93.720373] hello: loading out-of-tree module taints kernel.
    [   93.726625] hello_init
    [   93.729093] register_chrdev_region success
    [   93.733210] class create success
    [   93.737712] cdev_add success
    # ./test
    open /dev/hello success! 
    # cd /sys/class/myclass/
    # ls
    hello
    # cd hello/
    # ls
    dev        power      subsystem  uevent
    # ls /dev/hello
    /dev/hello
  • 相关阅读:
    Redis中统计各种数据大小的方法
    Redis配置文件详解
    Redis服务器的启动过程分析
    在Mac OS上安装Vagrant和Docker的教程
    使用Redis实现用户积分排行榜的教程
    Redis教程(一):Redis简介
    Redis教程(二):String数据类型
    Redis教程(四):Hashes数据类型
    Redis教程(六):Sorted-Sets数据类型
    Redis教程(八):事务详解
  • 原文地址:https://www.cnblogs.com/ZQQH/p/8575674.html
Copyright © 2020-2023  润新知