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
原文地址:https://www.cnblogs.com/ZQQH/p/8575674.html