• register_chrdev和cdev_init区别


    register_chrdev
    缺点:
    一个内核只能有255个字符驱动程序
    2.6内核后建议把register_chrdev展开.
    以前想以主设备号为下标,在chrdevs里找到之前注册的file_operations,而现在以主设备号和次设备号来找到该结构体。
    展开为1.register_chrdev_region注册区域
           /alloc_chrdev_region  region区域的意思为某个(主,次)到某个(主,次+n)设备号都对应这个驱动。以前是(主,0)到(主,255)都对应这个结构体一下子都占住位置,展开后可以缩小主设备号次设备号到某个次设备号范围
           
         2.cdev_init
         3.cdev_add
    
    
    /**
     * __register_chrdev() - create and register a cdev occupying a range of minors
     * @major: major device number or 0 for dynamic allocation
     * @baseminor: first of the requested range of minor numbers
     * @count: the number of minor numbers required
     * @name: name of this range of devices
     * @fops: file operations associated with this devices
     *
     * If @major == 0 this functions will dynamically allocate a major and return
     * its number.
     *
     * If @major > 0 this function will attempt to reserve a device with the given
     * major number and will return zero on success.
     *
     * Returns a -ve errno on failure.
     *
     * The name of this device has nothing to do with the name of the device in
     * /dev. It only helps to keep track of the different owners of devices. If
     * your module name has only one type of devices it's ok to use e.g. the name
     * of the module here.
     */
    int __register_chrdev(unsigned int major, unsigned int baseminor,
    		      unsigned int count, const char *name,
    		      const struct file_operations *fops)
    {
    	struct char_device_struct *cd;
    	struct cdev *cdev;
    	int err = -ENOMEM;
    
    	cd = __register_chrdev_region(major, baseminor, count, name);
    	if (IS_ERR(cd))
    		return PTR_ERR(cd);
    
    	cdev = cdev_alloc();
    	if (!cdev)
    		goto out2;
    
    	cdev->owner = fops->owner;
    	cdev->ops = fops;
    	kobject_set_name(&cdev->kobj, "%s", name);
    
    	err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
    	if (err)
    		goto out;
    
    	cd->cdev = cdev;
    
    	return major ? 0 : cd->major;
    out:
    	kobject_put(&cdev->kobj);
    out2:
    	kfree(__unregister_chrdev_region(cd->major, baseminor, count));
    	return err;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    cdev_init

    /**
     * cdev_init() - initialize a cdev structure
     * @cdev: the structure to initialize
     * @fops: the file_operations for this device
     *
     * Initializes @cdev, remembering @fops, making it ready to add to the
     * system with cdev_add().
     */
    void cdev_init(struct cdev *cdev, const struct file_operations *fops)
    {
    	memset(cdev, 0, sizeof *cdev);
    	INIT_LIST_HEAD(&cdev->list);
    	kobject_init(&cdev->kobj, &ktype_cdev_default);
    	cdev->ops = fops;
    }
    ----------------------使用--------------------------
    /* nsc_gpio uses dev_dbg(), so needs this */
    	scx200_gpio_ops.dev = &pdev->dev;
    
    	if (major) {
    		devid = MKDEV(major, 0);
    		rc = register_chrdev_region(devid, MAX_PINS, "scx200_gpio");//如果指定了主设备号用这函数devid为从哪开始((major, 0)对应ops,(major, 1-255)其他不对应
    	} else {
    		rc = alloc_chrdev_region(&devid, 0, MAX_PINS, "scx200_gpio");//第二个参数为次设备号基地址,MAX_PINS为个数
    		major = MAJOR(devid);
    	}
    	if (rc < 0) {
    		dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc);
    		goto undo_platform_device_add;
    	}
    
    	cdev_init(&scx200_gpio_cdev, &scx200_gpio_fileops);
    	cdev_add(&scx200_gpio_cdev, devid, MAX_PINS);
    class_create
    device_create//如果让系统自动创建设备节点,需要创建类和device
    	return 0; /* succeed */
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    【ACM】简单题(3)
    mac pro M1(ARM)安装:安装zookeeper可视化工具PrettyZoo、ZooKeeperAssistant
    MATLAB编程:绘制折线图 以及 画图的一些小技巧
    史上最强 Java 学习路线图!
    合宙Air724UG LuatOS-Air LVGL API控件-截屏(Screenshots)
    【网络通信三】研华网关Modbus服务设置
    iOS经典面试题之深入解析objc对象的内存空间、数据结构以及isa指针的理解
    万字好文:大报文问题实战
    详细图文教你如何提高汉字小达人个人信息录入的速度和准确度
    分组子集对齐后再做差集
  • 原文地址:https://blog.csdn.net/qq_56926420/article/details/125456079