ldd3 chapter3 字符驱动简单记录
来源:互联网 发布:淘宝网能用货到付款 编辑:程序博客网 时间:2024/06/07 03:06
动态分配节点号:
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)
删除节点号:
void unregister_chrdev_region(dev_t from, unsigned count)
动态分配cdev:
struct cdev *cdev_alloc(void)初始化cdev,并绑定file_operations:
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
将cdev和节点号绑定:
int cdev_add(struct cdev *, dev_t, unsigned);
删除cdev:
void cdev_del(struct cdev *p)
代码:
#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/list.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/errno.h>#include <asm/uaccess.h>#include <linux/semaphore.h>loff_t scull_llseek(struct file *filp, loff_t f_ops, int flag);ssize_t scull_read(struct file *filp, char __user * buf, size_t count, loff_t *f_ops);ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops);int scull_ioctl(struct inode *p_inode, struct file *filp, unsigned int cmd, unsigned long args);int scull_open(struct inode *p_inode, struct file *filp);int scull_release(struct inode *p_inode, struct file *filp);struct file_operations scull_fops = {.owner = THIS_MODULE,.llseek = scull_llseek,.read = scull_read,.write = scull_write,.ioctl = scull_ioctl,.open = scull_open,.release = scull_release,};struct scull_qset{struct list_head qset_node;void **data;};struct scull_dev{struct list_head qset_head;int quantum;int qset;unsigned long size;dev_t dev_t;struct cdev cdev;struct semaphore sem;};struct scull_dev g_scull_dev;//根据index 返回p_qset结构,如果没有就创建一个struct scull_qset *scull_follow(struct scull_dev* dev, int index){int i = 0;struct list_head * p_qset_node;struct scull_qset *p_qset;list_for_each(p_qset_node, &dev->qset_head){if((i++) == index){return container_of(p_qset_node, struct scull_qset, qset_node);}}p_qset = (struct scull_qset *)kmalloc(sizeof(struct scull_qset), GFP_KERNEL);if (p_qset == NULL)return NULL;memset(p_qset, 0, sizeof(struct scull_qset));p_qset->data = kmalloc(dev->qset * sizeof(char *), GFP_KERNEL);if (p_qset->data == NULL){kfree(p_qset);return NULL;}memset(p_qset->data, 0, dev->qset * sizeof(char *));list_add_tail(&p_qset->qset_node, &dev->qset_head);return p_qset;}int scull_trim(struct scull_dev *dev){struct list_head *p_qset_node = NULL;struct scull_qset *p_qset;int i;while(!list_empty(&dev->qset_head)){p_qset_node = dev->qset_head.next;p_qset = container_of(p_qset_node, struct scull_qset, qset_node);for (i = 0; i < dev->qset; i++){kfree(p_qset->data[i]);}list_del(p_qset_node);kfree(p_qset);}dev->size = 0;return 0;}loff_t scull_llseek(struct file *filp, loff_t f_ops, int flag){printk(KERN_ERR"llseek\n");return 0;}ssize_t scull_read(struct file *filp, char __user * buf, size_t count, loff_t *f_ops){struct scull_dev *dev = filp->private_data;struct scull_qset *p_qset;int qset_size = dev->quantum * dev->qset;int qset_index,qset_rest;int quan_index,quan_rest;ssize_t retval = 0;if (down_interruptible(&dev->sem))return -ERESTARTSYS;qset_index = (long)*f_ops / qset_size;qset_rest = (long)*f_ops % qset_size;quan_index = qset_rest / dev->quantum;quan_rest = qset_rest % dev->quantum;if (*f_ops > dev->size)goto out;if ((*f_ops + count) > dev->size){count = dev->size - *f_ops;}p_qset = scull_follow(dev, qset_index);if (p_qset == NULL || p_qset->data == NULL || p_qset->data[quan_index] == NULL){goto out; }if (count > (dev->quantum - quan_rest)){count = dev->quantum - quan_rest;}if (copy_to_user(buf, p_qset->data[quan_index] + quan_rest, count)){retval = -EFAULT;goto out;}*f_ops += count;retval = count;out:up(&dev->sem);return retval;}ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops){struct scull_dev *dev = filp->private_data;struct scull_qset *p_qset = NULL;int qset_size = dev->quantum * dev->qset;int qset_index,qset_rest;int quan_index,quan_rest;ssize_t retval = -ENOMEM;if(down_interruptible(&dev->sem))return -ERESTARTSYS;qset_index = (long)*f_ops / qset_size;qset_rest = (long)*f_ops % qset_size;quan_index = qset_rest / dev->quantum;quan_rest = qset_rest % dev->quantum;p_qset = scull_follow(dev, qset_index);if (p_qset == NULL)goto out;if (p_qset->data[quan_index] == NULL){p_qset->data[quan_index] = kmalloc(dev->quantum, GFP_KERNEL);if (p_qset->data[quan_index] == NULL)goto out;}if (count > (dev->quantum - quan_rest)){count = dev->quantum - quan_rest;}if (copy_from_user(p_qset->data[quan_index] + quan_rest, buf, count)){retval = -EFAULT;goto out;}*f_ops += count;retval = count;if (dev->size < *f_ops)dev->size = *f_ops;out:up(&dev->sem);return retval;}int scull_ioctl(struct inode *p_inode, struct file *filp, unsigned int cmd, unsigned long args){printk(KERN_ERR"ioctl\n");return 0;}int scull_open(struct inode *p_inode, struct file *filp){struct scull_dev *dev = NULL;dev = container_of(p_inode->i_cdev, struct scull_dev, cdev);filp->private_data = dev;//如果以append模式打开,则文件指针指向末尾if (filp->f_flags & O_APPEND){filp->f_pos = p_inode->i_size;}//如果以trunc模式打开,则将dev内容清除if (filp->f_flags & O_TRUNC){scull_trim(dev);p_inode->i_size = dev->size;}printk(KERN_ERR"file size = %ld\n",dev->size);return 0;}int scull_release(struct inode *p_inode, struct file *filp){struct scull_dev *dev = filp->private_data;if(down_interruptible(&dev->sem))return -ERESTARTSYS;//更新文件大小p_inode->i_size = dev->size;up(&dev->sem);return 0;}static int scull_init(void){int result = 0;//分配节点号if ((result = alloc_chrdev_region(&g_scull_dev.dev_t, 0, 4, "scull")) < 0){printk(KERN_ERR"alloc_chrdev_region error!\n");return result;}//初始化cdev结构,并绑定file_operations和节点号cdev_init(&g_scull_dev.cdev, &scull_fops);cdev_add(&g_scull_dev.cdev, g_scull_dev.dev_t, 4);printk(KERN_ERR"major = %d,minor = %d\n",MAJOR(g_scull_dev.dev_t),MINOR(g_scull_dev.dev_t));//初始化设备结构体g_scull_dev.qset = 4096;g_scull_dev.quantum = 4096;INIT_LIST_HEAD(&g_scull_dev.qset_head);sema_init(&g_scull_dev.sem, 1);return 0;}static void scull_exit(void){cdev_del(&g_scull_dev.cdev);unregister_chrdev_region(g_scull_dev.dev_t, 1);scull_trim(&g_scull_dev);return;}module_init(scull_init);module_exit(scull_exit);MODULE_LICENSE("Dual BSD/GPL");
Makfile:
obj-m += scull.oKDIR := /home/linux-2.6.32.2PWD = $(shell pwd)all:make -C $(KDIR) M=$(PWD) modulesclean:rm -rf *.o
测试:
[root@FriendlyARM /nfs]# insmod scull.ko
major = 253,minor = 0
[root@FriendlyARM /nfs]# mknod /dev/scull0 c 253 0
0 0
- ldd3 chapter3 字符驱动简单记录
- (LDD3读书记录)Chapter-3:字符驱动
- LDD3读书笔记--字符驱动
- LDD3 字符设备驱动
- LDD3笔记——字符设备驱动简单分析
- LDD3《Linux设备驱动》中的最简单的字符设备驱动实现与测试
- 简单字符设备驱动代码+注释(ldd3第三章例子)
- ldd3代码分析(高级字符驱动)
- LDD3笔记:第三章 字符设备驱动
- LDD3翻译:第三章 (字符驱动)
- 学习Ldd3--字符设备驱动(第三章)
- LDD3读书笔记-----高级字符驱动操作
- (LDD3实践)Chapter-3:字符驱动
- ldd3笔记_字符设备驱动
- LDD3 Chapter3 分配主设备号测试代码
- 字符设备驱动相关函数及数据结构简介 (ldd3)
- 字符设备驱动相关函数及数据结构简介 (ldd3)
- LDD3学习笔记(3):字符驱动1
- 谷歌技术"三宝"之BigTable
- http://blog.csdn.net/change518/article/details/8004827
- 装好Centos7后提示Initial setup of CentOS Linux 7 (core)
- Shader 妖怪手表放大镜 20160619
- Linux基础篇和服务器篇教程
- ldd3 chapter3 字符驱动简单记录
- 冒泡排序-JS代码实现
- 【好玩的计算机视觉】自动玩寻找不一样的色彩4399小游戏
- Linux 下shell编程
- 【leetcode】169. Majority Element
- Maven插件:maven-javadoc-plugin
- KMP算法
- Linux镜像下载
- 第一次使用OD和IDA动静结合找出软件的注册算法