llinux 驱动——字符驱动

来源:互联网 发布:华为天际通数据服务 编辑:程序博客网 时间:2024/05/16 14:02

一、基本概念
主设备号与次设备号: 可以理解为主设备号对应一个驱动程序,次设备号对应一个设备。

二、重要的数据结构
struct file_operations : 文件操作 可参考: http://blog.csdn.net/sunsea1026/article/details/6586143
struct file : 文件 可参考: http://blog.csdn.net/yuzhihui_no1/article/details/51272563
struct inode : 内部节点 可参考: http://blog.csdn.net/fantasyhujian/article/details/9151615

三、分配及释放设备号

int register_chrdev_region(dev_t first, unsigned int count, char *name);int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);

register_chrdev_region : 明确主设备号时使用
alloc_chrdev_region :主设备号未明确时使用

count : 决定了可以使用的设备数量,即在 在调用cdev_add 后,mknod /dev/* c majorminor /dev/* 下面有效的设备数量。 如 name=”scull”, count=4, minor =0, 则对应的 通过mknod /dev/* c $major [0-3] /dev/* 建立的设备节点 /dev/scull[0-3]设备节点一一对应。

倾向于 使用alloc_chrdev_region 动态分配主设备号

字符设备注册模型

static void scull_setup_cdev(struct scull_dev *dev, int index){    int err, devno = MKDEV(scull_major, scull_minor + index);    cdev_init(&dev->cdev, &scull_fops);    dev->cdev.owner = THIS_MODULE;    dev->cdev.ops = &scull_fops;    err = cdev_add (&dev->cdev, devno, 1);    /* Fail gracefully if need be */    if (err)    printk(KERN_NOTICE "Error %d adding scull%d", err, index);}

早期也用进行设备注册

int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);int unregister_chrdev(unsigned int major, const char *name);

container_of :函数通过inode 节点中的i_cdev 字段,找到字符结构的首地址

container_of(pointer, container_type, container_field);eg:struct scull_dev *dev; /* device information */dev = container_of(inode->i_cdev, struct scull_dev, cdev);filp->private_data = dev; /* for other methods */int scull_open(struct inode *inode, struct file *filp){    struct scull_dev *dev; /* device information */    dev = container_of(inode->i_cdev, struct scull_dev, cdev);    filp->private_data = dev; /* for other methods */    /* now trim to 0 the length of the device if open was write-only */    if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) {        scull_trim(dev); /* ignore errors */    }return 0; /* success */}

此inode 是内存中的inode, 需要时才创建