设备驱动学习之字符设备驱动接口

每个设备对应一个设备号,由主设备号(major number)和次设备号(minor number)

类型为 dev_t:有以下三个宏进行操作,位置include/linux/kdev_t.h

#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))    //根据主次设备号生成设备号

分配和释放设备号接口,位置 fs/char_dev.c:

注册一个预定设备号

/**
 * register_chrdev_region() - register a range of device numbers
 * @from: the first in the desired range of device numbers; must include
 *        the major number.
 * @count: the number of consecutive device numbers required
 * @name: the name of the device or driver.
 *
 * Return value is zero on success, a negative error code on failure.
 */
int register_chrdev_region(dev_t from, 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)


设备号


描述字符设备的结构体位置在include/linux/cdev.h,为

struct cdev {
	struct kobject kobj;
	struct module *owner;
	const struct file_operations *ops;
	struct list_head list;
	dev_t dev;
	unsigned int count;
};


对应的接口函数位置在fs/char_dev.c,有

静态初始化函数

/**    
 * 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;
}



动态初始化函数

/**
 * 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;
}


添加cdev设备  :用于模块加载函数中

/**
 * 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);
}


删除设备:用于模块卸载函数中

/**
 * 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);
}



设备初始化顺序:

1.分配设备号  register_chrdev_region 或 alloc_chrdev_region

2.初始化cdev   cdev_init()   初始化时会将cdev和file_operations关联

3.添加cdev     cdev_add


如果同时存在多个字符设备,可以通过inode->i_cdev区分,如下:

struct my_dev * dev;
dev  = container_of(inode->i_cdev, my_dev, cdev)
filp->private_data = dev;


驱动模块使用:

1.insmod

2.创建节点 mknod /dev/my_dev c major minor

3.操作/dev/my_dev





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值