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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

设备驱动技术实验五.docx

1、设备驱动技术实验五嵌入式设备驱动技术课程实验报告班 级: 学 号: (需要填写) 姓 名: (需要填写) 指导老师: 成 绩: 实验五 Linux设备驱动中的并发控制一、目的与任务目的:了解Linux内核中的并发控制, 及熟悉并发与竞态、中断屏蔽、原子操作、自旋锁、信号量、互斥体机制。任务:增加并发控制后的globalmem模块的编程、编译与测试。二、内容、要求与安排方式1、实验内容与要求:1)原子操作; 2)自旋锁;3)信号量、互斥体机制。2、实验安排方式:采用1人1组,上机在Linux系统下进行编程实验。三、实验设备1、所用设备:PC机一台四、实验过程1)原子操作;所谓原子操作,就是该操作

2、绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位,因此这里的原子实际是使用了物理学里的物质微粒的概念。原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义都定义在内核源码树的include/asm/atomic.h文件中,它们都使用汇编语言实现,因为C语言并不能实现这样的操作。原子操作主要用于实现资源计数,很多引用计数(refcnt)就是通过原子操作实现的。原子类型定义如下: volatile修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。原子操作API包括:0.该函数对原子类型的

3、变量进行原子读操作,它返回原子类型的变量v的值。1.该函数设置原子类型的变量v的值为iatomic_set(atomic_t * v, int i);2.该函数给原子类型的变量v增加值i。void atomic_add(int i, atomic_t *v);3.该函数从原子类型的变量v中减去i。atomic_sub(int i, atomic_t *v);4.该函数从原子类型的变量v中减去i,并判断结果是否为0,如果为0,返回真,否则返回假。int atomic_sub_and_test(int i, atomic_t *v);5.该函数对原子类型变量v原子地增加1。void atomic_

4、inc(atomic_t *v);6.该函数对原子类型的变量v原子地减1void atomic_dec(atomic_t *v);7.该函数对原子类型的变量v原子地减1,并判断结果是否为0,如果为0,返回真,否则返回假。int atomic_dec_and_test(atomic_t *v);8.该函数对原子类型的变量v原子地增加1,并判断结果是否为0,如果为0,返回真,否则返回假。int atomic_inc_and_test(atomic_t *v);9.该函数对原子类型的变量v原子地增加I,并判断结果是否为负数,如果是,返回真,否则返回假。int atomic_add_negative(

5、int i, atomic_t *v);10.该函数对原子类型的变量v原子地增加i,并且返回指向v的指针。int atomic_add_return(int i, atomic_t *v);11.该函数从原子类型的变量v中减去i,并且返回指向v的指针。int atomic_sub_return(int i, atomic_t *v);12.该函数对原子类型的变量v原子地增加1并且返回指向v的指针。int atomic_inc_return(atomic_t * v);13.该函数对原子类型的变量v原子地减1并且返回指向v的指针。int atomic_dec_return(atomic_t *

6、v);2)自旋锁;自旋锁原语要求的包含文件是 . 一个实际的锁有类型 spinlock_t. 象任何其他数据结构, 一个 自旋锁必须初始化. 这个初始化可以在编译时完成, 如下: spinlock_t my_lock = SPIN_LOCK_UNLOCKED; 或者在运行时使用: void spin_lock_init(spinlock_t *lock);在进入一个临界区前, 你的代码必须获得需要的 lock , 用: void spin_lock(spinlock_t *lock);注意所有的自旋锁等待是, 由于它们的特性, 不可中断的. 一旦调用 spin_lock, 将自旋直到锁变为可用

7、.为释放一个已获得的锁, 传递它给:void spin_unlock(spinlock_t *lock);4 个函数可以加锁一个自旋锁: void spin_lock(spinlock_t *lock); void spin_lock_irqsave(spinlock_t *lock, unsigned long flags); void spin_lock_irq(spinlock_t *lock); void spin_lock_bh(spinlock_t *lock)4 个方法释放一个自旋锁void spin_unlock(spinlock_t *lock); void spin_unl

8、ock_irqrestore(spinlock_t *lock, unsigned long flags); void spin_unlock_irq(spinlock_t *lock); void spin_unlock_bh(spinlock_t *lock);阻塞的自旋锁操作: int spin_trylock(spinlock_t *lock); int spin_trylock_bh(spinlock_t *lock);2 种方式被声明和被初始化: rwlock_t my_rwlock = RW_LOCK_UNLOCKED; /* Static way */ rwlock_t my_

9、rwlock; rwlock_init(&my_rwlock); /* Dynamic way */3)信号量、互斥体机制。为了记录可用资源的数量,需要一个count计数,标记当前可用资源数量。需要一个count计数和等待进程的链表头即可。描述信号量的结构体如下。在linux中,需要一个结构体记录当前的进程信息(task_struct)。struct semaphore_waiter的list成员是当进程无法获取信号量的时候挂入semaphore的wait_list成员。task成员就是记录后续被唤醒的进程信息。一切准备就绪,现在就可以实现信号量的申请函数。(1).如果信号量标记的资源还有剩余

10、,自然可以成功获取信号量。只需要递减可用资源计数。(2).既然无法获取信号量,就需要将当前进程挂入信号量的等待队列链表上。(3).schedule()主要是触发任务调度的示意函数,主动让出CPU使用权。在让出之前,需要将当前进程从运行队列上移除。既然mutex是一种二值信号量,因此就不需要像semaphore那样需要一个count计数。由于mutex具有“持锁者才能解锁”的特点,所以我们需要一个变量owner记录持锁进程。释放锁的时候必须是同一个进程才能释放。当然也需要一个链表头,主要用来便利睡眠等待的进程。原理和semaphore及其相似,因此在代码上也有体现。struct mutex_wa

11、iter的list成员是当进程无法获取互斥量的时候挂入mutex的wait_list链表。首先实现申请互斥量的函数。(1).当mutex-owner的值为0的时候,代表没有任何进程持有锁。因此可以直接申请成功。然后,记录当前申请锁进程的task_struct。(2).既然不能获取互斥量,自然就需要睡眠等待,挂入等待链表。 互斥量的释放代码实现也同样和semaphore有很多相似之处。(1).mutex具有“持锁者才能解锁”的特点就是在这行代码体现。(2).如果等待链表没有进程,那么自然只需要将mutex-owner置0,代表没有锁是释放状态。(3).mutex-owner的值改成当前可以持锁进

12、程的task_struct。(4).从等待进程链表取出第一个进程,并从链表上移除。然后就是唤醒该进程。五、程序清单1)原子操作;原子操作函数如下:atomic_read(atomic_t * v);atomic_set(atomic_t * v, int i);void atomic_add(int i, atomic_t *v);atomic_sub(int i, atomic_t *v);int atomic_sub_and_test(int i, atomic_t *v);void atomic_inc(atomic_t *v);void atomic_dec(atomic_t *v);

13、int atomic_dec_and_test(atomic_t *v);int atomic_inc_and_test(atomic_t *v);int atomic_add_negative(int i, atomic_t *v);int atomic_add_return(int i, atomic_t *v);int atomic_sub_return(int i, atomic_t *v);int atomic_inc_return(atomic_t * v);int atomic_dec_return(atomic_t * v); 2)自旋锁;自旋锁函数spinlock_t my_

14、lock = SPIN_LOCK_UNLOCKED; void spin_lock_init(spinlock_t *lock);void spin_lock(spinlock_t *lock);void spin_unlock(spinlock_t *lock);void spin_lock(spinlock_t *lock); void spin_lock_irqsave(spinlock_t *lock, unsigned long flags); void spin_lock_irq(spinlock_t *lock); void spin_lock_bh(spinlock_t *lo

15、ck)void spin_unlock(spinlock_t *lock); void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); void spin_unlock_irq(spinlock_t *lock); void spin_unlock_bh(spinlock_t *lock);int spin_trylock(spinlock_t *lock); int spin_trylock_bh(spinlock_t *lock);rwlock_t my_rwlock = RW_LOCK_UNLOCKED; /*

16、 Static way */ rwlock_t my_rwlock; rwlock_init(&my_rwlock); /* Dynamic way */3)信号量、互斥体机制。描述信号量的结构体struct semaphore unsigned int count; struct list_head wait_list;结构体记录当前的进程信息struct semaphore_waiter struct list_head list; struct task_struct *task;实现信号量的申请函数void down(struct semaphore *sem) struct sema

17、phore_waiter waiter; if (sem-count 0) sem-count-; /* 1 */ return; waiter.task = current; /* 2 */ list_add_tail(&waiter.list, &sem-wait_list); /* 2 */ schedule(); /* 3 */两个类似的结构体分别描述mutexstruct mutex_waiter struct list_head list; struct task_struct *task; struct mutex long owner; struct list_head wai

18、t_list;申请互斥量的函数void mutex_take(struct mutex *mutex) struct mutex_waiter waiter; if (!mutex-owner) mutex-owner = (long)current; /* 1 */ return; waiter.task = current; list_add_tail(&waiter.list, &mutex-wait_list); /* 2 */ schedule(); /* 2 */互斥量的释放代码int mutex_release(struct mutex *mutex) struct mutex_

19、waiter waiter; if (mutex-owner != (long)current) /* 1 */ return -1; if (list_empty(&mutex-wait_list) mutex-owner = 0; /* 2 */ return 0; waiter = list_first_entry(&mutex-wait_list, struct mutex_waiter, list); list_del(&waiter-list); mutex-owner = (long)waiter-task; /* 3 */ wake_up_process(waiter-task); /* 4 */ return 0;六、实验体会(需要填写)指导教师评语:

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

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