ImageVerifierCode 换一换
格式:DOCX , 页数:6 ,大小:240.55KB ,
资源ID:11703729      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11703729.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux字符设备驱动.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux字符设备驱动.docx

1、Linux字符设备驱动 实验二:Linux字符设备驱动一字符设备驱动实现的方法包括Write, Read, Poll, Icotl, Mmap, Llseek等。二字符设备驱动的主要内容:并发控制,阻塞与非阻塞,异步通知。三字符设备驱动的主要文件:globalfifo.c Makefile globalfifo_test,globalfifo.c。四.驱动程序如下:#include #include #include #include #include #include #include #include #include #include #include #include #include

2、 /* device_create()*/#define GLOBALFIFO_SIZE 24 /*全局fifo最大4K字节*/#define FIFO_CLEAR 0x1 /*清0全局内存的长度*/#define GLOBALFIFO_MAJOR 249 /*预设的globalfifo的主设备号*/static int globalfifo_major = GLOBALFIFO_MAJOR;/*globalfifo设备结构体*/struct globalfifo_dev struct cdev cdev; /*cdev结构体*/ unsigned int current_len; /*fif

3、o有效数据长度*/ unsigned char memGLOBALFIFO_SIZE; /*全局内存*/ struct semaphore sem; /*并发控制用的信号量*/ wait_queue_head_t r_wait; /*阻塞读用的等待队列头*/ wait_queue_head_t w_wait; /*阻塞写用的等待队列头*/;struct globalfifo_dev *globalfifo_devp; /*设备结构体指针*/*文件打开函数*/int globalfifo_open(struct inode *inode, struct file *filp) /*将设备结构体指

4、针赋值给文件私有数据指针*/ filp-private_data = globalfifo_devp; return 0;/*文件释放函数*/int globalfifo_release(struct inode *inode, struct file *filp) return 0;/* ioctl设备控制函数 */static int globalfifo_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg) struct globalfifo_dev *dev = filp-

5、private_data;/*获得设备结构体指针*/ switch (cmd) case FIFO_CLEAR: down(&dev-sem); /* 获得信号量 */ dev-current_len = 0; memset(dev-mem,0,GLOBALFIFO_SIZE);up(&dev-sem); /* 释放信号量 */printk(KERN_INFO globalfifo is set to zeron); break; default: return - EINVAL; return 0;static unsigned int globalfifo_poll(struct file

6、 *filp, poll_table *wait) unsigned int mask = 0; struct globalfifo_dev *dev = filp-private_data; /*获得设备结构体指针*/ down(&dev-sem); poll_wait(filp, &dev-r_wait, wait);/*把读等待队列添加到poll_table*/ poll_wait(filp, &dev-w_wait, wait);/*把写等待队列添加到poll_table*/ /*fifo非空 表示可读*/ if (dev-current_len != 0) mask |= POLLI

7、N | POLLRDNORM; /*标示数据可获得*/ /*fifo非满 表示可写*/ if (dev-current_len != GLOBALFIFO_SIZE) mask |= POLLOUT | POLLWRNORM; /*标示数据可写入*/ up(&dev-sem); return mask;/*globalfifo读函数*/static ssize_t globalfifo_read(struct file *filp, char _user *buf, size_t count, loff_t *ppos) int ret; struct globalfifo_dev *dev

8、= filp-private_data;DECLARE_WAITQUEUE(wait, current); down(&dev-sem); /* 获得信号量 */ add_wait_queue(&dev-r_wait, &wait); /* 进入读等待队列头 */ /* 等待FIFO非空 */ if (dev-current_len = 0) if (filp-f_flags &O_NONBLOCK) ret = - EAGAIN; goto out; _set_current_state(TASK_INTERRUPTIBLE); /* 改变进程状态为睡眠 */ up(&dev-sem); s

9、chedule(); /* 调度其他进程执行 */ if (signal_pending(current) /* 如果是因为信号唤醒 */ ret = - ERESTARTSYS; goto out2; down(&dev-sem); /* 拷贝到用户空间 */ if (count dev-current_len) count = dev-current_len; if (copy_to_user(buf, dev-mem, count) ret = - EFAULT; goto out; else memcpy(dev-mem, dev-mem + count, dev-current_le

10、n - count); /* fifo数据前移 */dev-current_len -= count; /* 有效数据长度减少 */ printk(KERN_INFO read %d bytes(s),current_len:%dn, count, dev-current_len);wake_up_interruptible(&dev-w_wait); /* 唤醒写等待队列 */ ret = count; out: up(&dev-sem); /* 释放信号量 */out2: remove_wait_queue(&dev-w_wait, &wait); /* 从附属的等待队列头移除 */set

11、_current_state(TASK_RUNNING); return ret;/*globalfifo写操作*/static ssize_t globalfifo_write(struct file *filp, const char _user *buf,size_t count, loff_t *ppos) struct globalfifo_dev *dev = filp-private_data;int ret; DECLARE_WAITQUEUE(wait, current);down(&dev-sem);add_wait_queue(&dev-w_wait, &wait);/*

12、 等待FIFO非满 */if (dev-current_len = GLOBALFIFO_SIZE) if (filp-f_flags &O_NONBLOCK) ret = - EAGAIN;goto out; _set_current_state(TASK_INTERRUPTIBLE); /* 改变进程状态为睡眠 */ up(&dev-sem);schedule(); /* 调度其他进程执行 */if (signal_pending(current) /* 如果是因为信号唤醒 */ret = - ERESTARTSYS;goto out2; down(&dev-sem); /* 获得信号量

13、*/*从用户空间拷贝到内核空间*/if (count GLOBALFIFO_SIZE - dev-current_len) count = GLOBALFIFO_SIZE - dev-current_len;if (copy_from_user(dev-mem + dev-current_len, buf, count)ret = - EFAULT;goto out; else dev-current_len += count;printk(KERN_INFO written %d bytes(s),current_len:%dn, count, dev-current_len);wake_u

14、p_interruptible(&dev-r_wait); /* 唤醒读等待队列 */ret = count;out:up(&dev-sem); /* 释放信号量 */out2:remove_wait_queue(&dev-w_wait, &wait); /* 从附属的等待队列头移除 */ set_current_state(TASK_RUNNING);return ret;static int memdev_mmap(struct file *filp, struct vm_area_struct *vma)struct mem_dev *dev = filp-private_data; /

15、*获得设备结构体指针*/ vma-vm_flags |= VM_IO;vma-vm_flags |= VM_RESERVED if (remap_pfn_range(vma,vma-vm_start,virt_to_phys(dev-data)PAGE_SHIFT, vma-vm_end - vma-vm_start, vma-vm_page_prot)return -EAGAIN; return 0;/*文件操作结构体*/static const struct file_operations globalfifo_fops = .owner = THIS_MODULE,.read = glo

16、balfifo_read, .write = globalfifo_write, .ioctl = globalfifo_ioctl, .poll = globalfifo_poll, .open = globalfifo_open, .release = globalfifo_release, .mmap=memdev_mmap,;/*初始化并注册cdev*/static void globalfifo_setup_cdev(struct globalfifo_dev *dev, int index)int err, devno = MKDEV(globalfifo_major, index

17、); cdev_init(&dev-cdev, &globalfifo_fops); dev-cdev.owner = THIS_MODULE; err = cdev_add(&dev-cdev, devno, 1); if (err) printk(KERN_NOTICE Error %d adding LED%d, err, index);/*设备驱动模块加载函数*/int globalfifo_init(void) struct class *myclass; int ret; dev_t devno = MKDEV(globalfifo_major, 0); /* 申请设备号*/ if

18、 (globalfifo_major) ret = register_chrdev_region(devno, 1, globalfifo); else /* 动态申请设备号 */ ret = alloc_chrdev_region(&devno, 0, 1, globalfifo); globalfifo_major = MAJOR(devno); if (ret sem); /*初始化信号量*/ init_waitqueue_head(&globalfifo_devp-r_wait); /*初始化读等待队列头*/ init_waitqueue_head(&globalfifo_devp-w

19、_wait); /*初始化写等待队列头*/ return 0;fail_malloc: unregister_chrdev_region(devno, 1); return ret;/*模块卸载函数*/void globalfifo_exit(void) cdev_del(&globalfifo_devp-cdev); /*注销cdev*/ kfree(globalfifo_devp); /*释放设备结构体内存*/ unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1); /*释放设备号*/MODULE_AUTHOR(Song Baohu

20、a);MODULE_LICENSE(Dual BSD/GPL);module_param(globalfifo_major, int, S_IRUGO);module_init(globalfifo_init);module_exit(globalfifo_exit);五.(1)驱动程序的Makefile:obj-$(CONFIG_GLOBALFIFO) +=GLOBALFIFO.o(2)驱动程序的Kconfig为:config GLOBALFIFO tristate zifushebeiqudong(3)进入控制界面如图:(4)驱动模块的产生:总结:通过对字符设备驱动的操作,在实验过程中,遇到了很多困难,感觉有好多知识很生疏,学到的知识也不能很好的运用到实践中,在编写字符设备驱动程序时,比如在测试写阻塞,就会遇见写阻塞通过不了的问题,经过老师的讲解。才知道对于内存分配不合理,在其他地方也会出现很多错误,但是,经过慢慢摸索,我也学到了很多知道,加强了这方面的一些不足,感觉自己在字符设备驱动方面有了很大提高。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1