添加字符设备

添加一个普通的字符设备一般需要如下一些步骤:

1. 字符设备声明:

static struct cdev *pcdev;
static dev_t ndev;
静态的声明了 一个字符设备 cdev, 和设备号 dev_t;

2. 模块加载过程中,添加一个字符设备:

static int demo_map_init(void)
{
        int err = 0;
        char *kstr;

 ...
        //动态申请一个 字符设备内存。
        pcdev = cdev_alloc();

        //字符设备初始化
        cdev_init(pcdev, &mmap_fops);

        //动态注册一个字符设备
        alloc_chrdev_region(&ndev, 0, 1, "mmap_dev");
        printk("major = %d, minor = %d\n", MAJOR(ndev), MINOR(ndev));
        pcdev->owner = THIS_MODULE;

        //向系统中 添加一个字符设备
        cdev_add(pcdev, ndev, 1);

 ...
}

struct cdev *cdev_alloc(void) --- 动态申请一块字符设备内存

/**
 * cdev_alloc() - allocate a cdev structure
 *
 * Allocates and returns a cdev structure, or NULL on failure.
 */
struct cdev *cdev_alloc(void)
{
        struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
        if (p) {
                INIT_LIST_HEAD(&p->list);
                kobject_init(&p->kobj, &ktype_cdev_dynamic);
        }
        return p;
}
void cdev_init(struct cdev *cdev, const struct file_operations *fops)  --- 初始化一个字符设备

/**
 * 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;
}
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
                        const char *name)         ------动态注册字符设备

/**
 * alloc_chrdev_region() - register a range of char device numbers
 * @dev: output parameter for first assigned number
 * @baseminor: first of the requested range of minor numbers
 * @count: the number of minor numbers required
 * @name: the name of the associated device or driver
 *
 * Allocates a range of char device numbers.  The major number will be
 * chosen dynamically, and returned (along with the first minor number)
 * in @dev.  Returns zero or a negative error code.
 */
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
                        const char *name)
{
        struct char_device_struct *cd;
        cd = __register_chrdev_region(0, baseminor, count, name);
        if (IS_ERR(cd))
                return PTR_ERR(cd);
        *dev = MKDEV(cd->major, cd->baseminor);
        return 0;
}
int cdev_add(struct cdev *p, dev_t dev, unsigned count) ---想系统中添加字符设备
/**             
 * cdev_add() - add a char device to the system
 * @p: the cdev structure for the device
 * @dev: the first device number for which this device is responsible
 * @count: the number of consecutive minor numbers corresponding to this
 *         device
 *      
 * cdev_add() adds the device represented by @p to the system, making it
 * live immediately.  A negative error code is returned on failure.
 */
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{       
        p->dev = dev;
        p->count = count;
        return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}
3.  卸载字符设备:

static void demo_map_exit(void)
{
        del_timer_sync(&timer);

        // 从系统中删除字符设备
        cdev_del(pcdev);

        //注销字符设备
        unregister_chrdev_region(ndev, 1);
        kunmap(pg);
        ClearPageReserved(pg);
        __free_pages(pg, 0);
}
void cdev_del(struct cdev *p) --- 从系统中删除字符设备

/**
 * cdev_del() - remove a cdev from the system
 * @p: the cdev structure to be removed
 *
 * cdev_del() removes @p from the system, possibly freeing the structure
 * itself.
 */
void cdev_del(struct cdev *p)
{
        cdev_unmap(p->dev, p->count);
        kobject_put(&p->kobj);
}
void unregister_chrdev_region(dev_t from, unsigned count) --- 注销count 个字符设备
/**
 * unregister_chrdev_region() - return a range of device numbers
 * @from: the first in the range of numbers to unregister
 * @count: the number of device numbers to unregister
 *
 * This function will unregister a range of @count device numbers,
 * starting with @from.  The caller should normally be the one who
 * allocated those numbers in the first place...
 */
void unregister_chrdev_region(dev_t from, unsigned count)
{
        dev_t to = from + count;
        dev_t n, next;

        for (n = from; n < to; n = next) {
                next = MKDEV(MAJOR(n)+1, 0);
                if (next > to)
                        next = to;
                kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值