Another character device driver written

Another character device driver written

In Linux2.6 kernel, a structure described cdev a character device;

cdev structure (include / linux / cdev.h) is defined as follows:

struct cdev {
    struct kobject kobj;               /* 内嵌的kobject对象 */
    struct module *owner;              /* 所属模块 */
    const struct file_operations *ops; /* 文件操作结构体 */
    struct list_head list;
    dev_t dev;                         /* 设备号 */
    unsigned int count;
};

dev cdev structural body member defines a device number, 32 bits, 12 primary device number, device number 20 ranking;

Macros can be obtained using the following major and minor numbers from dev, and dev_t generated by the major and minor numbers, defined as follows:

#define MINORBITS   20
#define MINORMASK   ((1U << MINORBITS) - 1)

#define MAJOR(dev)  ((unsigned int) ((dev) >> MINORBITS)) /* 获取主设备号 */
#define MINOR(dev)  ((unsigned int) ((dev) & MINORMASK))  /* 获取次设备号 */
#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))      /* 根据主次设备号生成dev*/

Another important member of file_operations cdev structure defines the interface function character device driver available to the virtual file system;

Linux2.6 kernel provides a set of functions for operating cdev structures, defined as follows:

/* 用于初始化cdev的成员,并建立cdev和file_operation之间的连接 */
void cdev_init(struct cdev *, const struct file_operations *);
/* 用于动态申请一个cdev内存 */
struct cdev *cdev_alloc(void);
void cdev_put(struct cdev *p);
/* 向系统添加一个cdev,完成字符设备的注册 */
int cdev_add(struct cdev *, dev_t, unsigned);
/* 向系统删除一个cdev,完成字符设备的注销 */
void cdev_del(struct cdev *);

For cdev_add () function call usually occurs in the character device driver module loading functions, a character register device to the system, before the following function should be called first application device number to the system:

/* 用于已知起始设备的设备号的情况 */
int register_chrdev_region(dev_t from, unsigned count, const char *name);
或者:
/* 用于设备号未知,向系统动态申请未被占用的设备号的情况 */
/* 调用该函数成功后,会把得到的设备号放入第一个参数dev中 */
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
            const char *name);

For cdev_del () function after the cancellation of a character device from the system, unregister_chrdev_region () should be called to release the device number of the original application;

Specific use are as follows:

/* 定义一个dev_t类型变量 */
dev_t dev_id;

static struct cdev xxx_cdev;
static int major;
static const struct file_operations xxx_fops = {
    .owner  = THIS_MODULE,
    .write  = xxx_write,
    .read   = xxx_read,
    .open   = xxx_open
};

/* 设备驱动模块加载函数 */
static int __init xxx_init(void)
{
    if (major) { /* 如果已知主设备号 */
        dev_id = MKDEV(major, 0);
        retval = register_chrdev_region(dev_id, 1, DEV_NAME);
    } else {
        retval = alloc_chrdev_region(&dev_id, 0, 1, DEV_NAME);
        major = MAJOR(dev_id);
    }
    cdev_init(&xxx_cdev, &xxx_fops);
    cdev_add(&xxx_cdev, dev_id, 1);
}

/* 设备驱动模块卸载函数 */
static void __exit xxx_exit(void)
{
    cdev_del(&xxx_cdev);
    unregister_chrdev_region(dev_id, 1);
}

Guess you like

Origin www.cnblogs.com/jasontian996/p/11519172.html