cdev简单解析

1. cdev是linux用来管理字符设备的结构体,其在内核中采用数组结构设计,这样系统中有多少个主设备号就约定了数组大小,此设备号采用链表管理,同一主设备号下可以有多个子设备。设备即文件,上层应用要访问设备,必须通过文件,cdev中包含file_operations结构体,该结构体就是驱动的文件操作集合。
(根据于说得)
2. cdev定义在include/linux/cdev.h中,如下。具体实现在fs/char_dev.c中。

#include <linux/kobject.h>
#include <linux/kdev_t.h>
#include <linux/list.h>

struct file_operations;
struct inode;
struct module;

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

void cdev_init(struct cdev *, const struct file_operations *); 
struct cdev *cdev_alloc(void);
void cdev_put(struct cdev *p);
int cdev_add(struct cdev *, dev_t, unsigned);
void cdev_del(struct cdev *);

void cd_forget(struct inode *);

extern struct backing_dev_info directly_mappable_cdev_bdi;
//fs/char_dev.c
/**
* 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. cdev函数

>>cdev定义有两种方式,struct cdev cdev;另外一种struct cdev *cdev; cdev=cdev_alloc();
一种静态声明定义,另一种动态分配。
>>cdev通过函数cdev_init()初始化,主要工作就是将file_operations和cdev关联起来。file_operations是字符驱动需要实现的主要内容。
>>cdev通过cdev_add()实现cdev的注册,所谓注册就是将cdev根据设备号(dev_t)添加到cdev数组(cdev_map)中供系统管理。
>>cdev通过cdev_del()将cdev从cdev_map中移除。
4. 设备号
申请设备号用如下两个函数:
alloc_chrdev_region() --自动分配设备号
register_chrdev_region() --分配已设定的设备号

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

5. more

参考:
http://www.embedu.org/Column/Column552.htm
http://blog.chinaunix.net/uid-24517893-id-161446.html

我是新手,详细讲解该代码实现的思路,编写的过程,以及用到的所有的函数的用法,意义:#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/uaccess.h> #include <linux/err.h> #define DEV_NAME "echo" #define BUF_SIZE 256 MODULE_LICENSE("GPL"); MODULE_AUTHOR("wyl"); MODULE_DESCRIPTION("Character device which prints written content with case conversion"); static int cap = 0; module_param(cap, int, 0644); MODULE_PARM_DESC(cap, "Convert input to uppercase (1: enable, 0: disable)"); static dev_t dev; static struct cdev my_cdev; static ssize_t mod_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){ char k_buf[BUF_SIZE]; size_t copy_size = min(count, (size_t)(BUF_SIZE - 1)); if(copy_from_user(k_buf, buf, copy_size)){ return -EFAULT; } k_buf[copy_size - 1] = '\0'; if(cap){ for(int i = 0; i < copy_size; i++){ if((k_buf[i] >= 'a') && (k_buf[i] <= 'z')){ k_buf[i] -= 32; } } } printk(KERN_INFO "echo : Written content : %s\n", k_buf); return count; } static const struct file_operations fops = { .owner = THIS_MODULE, .write = mod_write, }; static int __init echo_init(void){ int ret; ret = alloc_chrdev_region(&dev, 0, 1, DEV_NAME); if(ret < 0){ printk(KERN_ERR "echo : Failed to allocate device number!\n"); return ret; } cdev_init(&my_cdev, &fops); my_cdev.owner = THIS_MODULE; ret = cdev_add(&my_cdev, dev, 1); if(ret < 0){ printk(KERN_ERR "echo : Failed to add cdev!\n"); unregister_chrdev_region(dev,1); return ret; } printk(KERN_INFO "echo : Module loaded! (major = %d, cap = %d)", MAJOR(dev),cap); return 0; } static void __exit echo_cleanup(void){ cdev_del(&my_cdev); unregister_chrdev_region(dev,1); printk(KERN_INFO "echo: Module unloaded!\n"); } module_init(echo_init); module_exit(echo_cleanup);
最新发布
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值