• 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
  • 相关阅读:
    CentOS常用基础命令汇总
    信息服务上线渗透检测网络安全检查报告和解决方案
    【深入】k-means和FCM的差别
    洛谷P2523 Problem c
    Linux下安装Docker(centOS 8)
    使用python setup.py报错:Upload failed (403) / Upload failed (400)
    苹果电脑数据恢复Disk Drill Enterprise
    Siemens-NXUG二次开发-创建倒斜角特征、边倒圆角特征、设置对象颜色、获取面信息[Python UF][20240605]
    java基于springboot同学校友录捐赠信息网站ssm-maven项目源码
    LeetCode 0304. 二维区域和检索 - 矩阵不可变
  • 原文地址:https://blog.csdn.net/qq_56926420/article/details/125456079