设备驱动技术实验五.docx

上传人:b****7 文档编号:10554074 上传时间:2023-02-21 格式:DOCX 页数:11 大小:128.08KB
下载 相关 举报
设备驱动技术实验五.docx_第1页
第1页 / 共11页
设备驱动技术实验五.docx_第2页
第2页 / 共11页
设备驱动技术实验五.docx_第3页
第3页 / 共11页
设备驱动技术实验五.docx_第4页
第4页 / 共11页
设备驱动技术实验五.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

设备驱动技术实验五.docx

《设备驱动技术实验五.docx》由会员分享,可在线阅读,更多相关《设备驱动技术实验五.docx(11页珍藏版)》请在冰豆网上搜索。

设备驱动技术实验五.docx

设备驱动技术实验五

 

《嵌入式设备驱动技术》

课程实验报告

 

班级:

学号:

(需要填写)

姓名:

(需要填写)

指导老师:

成绩:

实验五Linux设备驱动中的并发控制

一、目的与任务

目的:

了解Linux内核中的并发控制,及熟悉并发与竞态、中断屏蔽、原子操作、自旋锁、信号量、互斥体机制。

任务:

增加并发控制后的globalmem模块的编程、编译与测试。

二、内容、要求与安排方式

1、实验内容与要求:

1)原子操作;

2)自旋锁;

3)信号量、互斥体机制。

2、实验安排方式:

采用1人1组,上机在Linux系统下进行编程实验。

三、实验设备

1、所用设备:

PC机一台

 

四、实验过程

1)原子操作;

所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位,因此这里的原子实际是使用了物理学里的物质微粒的概念。

原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义都定义在内核源码树的include/asm/atomic.h文件中,它们都使用汇编语言实现,因为C语言并不能实现这样的操作。

原子操作主要用于实现资源计数,很多引用计数(refcnt)就是通过原子操作实现的。

原子类型定义如下:

volatile修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。

 

原子操作API包括:

 

0.该函数对原子类型的变量进行原子读操作,它返回原子类型的变量v的值。

1.该函数设置原子类型的变量v的值为i

atomic_set(atomic_t*v,inti);

2.该函数给原子类型的变量v增加值i。

voidatomic_add(inti,atomic_t*v);

3.该函数从原子类型的变量v中减去i。

atomic_sub(inti,atomic_t*v);

4.该函数从原子类型的变量v中减去i,并判断结果是否为0,如果为0,返回真,否则返回假。

intatomic_sub_and_test(inti,atomic_t*v);

5.该函数对原子类型变量v原子地增加1。

 

voidatomic_inc(atomic_t*v);

6.该函数对原子类型的变量v原子地减1

voidatomic_dec(atomic_t*v);

7.该函数对原子类型的变量v原子地减1,并判断结果是否为0,如果为0,返回真,否则返回假。

intatomic_dec_and_test(atomic_t*v);

8.该函数对原子类型的变量v原子地增加1,并判断结果是否为0,如果为0,返回真,否则返回假。

intatomic_inc_and_test(atomic_t*v);

9.该函数对原子类型的变量v原子地增加I,并判断结果是否为负数,如果是,返回真,否则返回假。

intatomic_add_negative(inti,atomic_t*v);

10.该函数对原子类型的变量v原子地增加i,并且返回指向v的指针。

 

intatomic_add_return(inti,atomic_t*v);

11.该函数从原子类型的变量v中减去i,并且返回指向v的指针。

 

intatomic_sub_return(inti,atomic_t*v);

12.该函数对原子类型的变量v原子地增加1并且返回指向v的指针。

 

intatomic_inc_return(atomic_t*v);

13.该函数对原子类型的变量v原子地减1并且返回指向v的指针。

intatomic_dec_return(atomic_t*v);

2)自旋锁;

自旋锁原语要求的包含文件是.一个实际的锁有类型spinlock_t.象任何其他数据结构,一个自旋锁必须初始化.这个初始化可以在编译时完成,如下:

spinlock_tmy_lock=SPIN_LOCK_UNLOCKED;

  或者在运行时使用:

voidspin_lock_init(spinlock_t*lock);

  在进入一个临界区前,你的代码必须获得需要的lock,用:

  voidspin_lock(spinlock_t*lock);

  注意所有的自旋锁等待是,由于它们的特性,不可中断的.一旦调用spin_lock,将自旋直到锁变为可用.

  为释放一个已获得的锁,传递它给:

  voidspin_unlock(spinlock_t*lock);

4个函数可以加锁一个自旋锁:

  voidspin_lock(spinlock_t*lock);

  voidspin_lock_irqsave(spinlock_t*lock,unsignedlongflags);

  voidspin_lock_irq(spinlock_t*lock);

  voidspin_lock_bh(spinlock_t*lock)

4个方法释放一个自旋锁

  voidspin_unlock(spinlock_t*lock);

  voidspin_unlock_irqrestore(spinlock_t*lock,unsignedlongflags);

  voidspin_unlock_irq(spinlock_t*lock);

  voidspin_unlock_bh(spinlock_t*lock);

阻塞的自旋锁操作:

  intspin_trylock(spinlock_t*lock);

  intspin_trylock_bh(spinlock_t*lock);

2种方式被声明和被初始化:

  rwlock_tmy_rwlock=RW_LOCK_UNLOCKED;/*Staticway*/

  rwlock_tmy_rwlock;

  rwlock_init(&my_rwlock);/*Dynamicway*/

3)信号量、互斥体机制。

为了记录可用资源的数量,需要一个count计数,标记当前可用资源数量。

需要一个count计数和等待进程的链表头即可。

描述信号量的结构体如下。

在linux中,需要一个结构体记录当前的进程信息(task_struct)。

structsemaphore_waiter的list成员是当进程无法获取信号量的时候挂入semaphore的wait_list成员。

task成员就是记录后续被唤醒的进程信息。

一切准备就绪,现在就可以实现信号量的申请函数。

(1).如果信号量标记的资源还有剩余,自然可以成功获取信号量。

只需要递减可用资源计数。

(2).既然无法获取信号量,就需要将当前进程挂入信号量的等待队列链表上。

(3).schedule()主要是触发任务调度的示意函数,主动让出CPU使用权。

在让出之前,需要将当前进程从运行队列上移除。

既然mutex是一种二值信号量,因此就不需要像semaphore那样需要一个count计数。

由于mutex具有“持锁者才能解锁”的特点,所以我们需要一个变量owner记录持锁进程。

释放锁的时候必须是同一个进程才能释放。

当然也需要一个链表头,主要用来便利睡眠等待的进程。

原理和semaphore及其相似,因此在代码上也有体现。

structmutex_waiter的list成员是当进程无法获取互斥量的时候挂入mutex的wait_list链表。

首先实现申请互斥量的函数。

(1).当mutex->owner的值为0的时候,代表没有任何进程持有锁。

因此可以直接申请成功。

然后,记录当前申请锁进程的task_struct。

(2).既然不能获取互斥量,自然就需要睡眠等待,挂入等待链表。

互斥量的释放代码实现也同样和semaphore有很多相似之处。

(1).mutex具有“持锁者才能解锁”的特点就是在这行代码体现。

(2).如果等待链表没有进程,那么自然只需要将mutex->owner置0,代表没有锁是释放状态。

(3).mutex->owner的值改成当前可以持锁进程的task_struct。

(4).从等待进程链表取出第一个进程,并从链表上移除。

然后就是唤醒该进程。

 

五、程序清单

1)原子操作;

原子操作函数如下:

atomic_read(atomic_t*v);

atomic_set(atomic_t*v,inti);

voidatomic_add(inti,atomic_t*v);

atomic_sub(inti,atomic_t*v);

intatomic_sub_and_test(inti,atomic_t*v);

voidatomic_inc(atomic_t*v);

voidatomic_dec(atomic_t*v);

intatomic_dec_and_test(atomic_t*v);

intatomic_inc_and_test(atomic_t*v);

intatomic_add_negative(inti,atomic_t*v);

intatomic_add_return(inti,atomic_t*v);

intatomic_sub_return(inti,atomic_t*v);

intatomic_inc_return(atomic_t*v);

intatomic_dec_return(atomic_t*v);

 

2)自旋锁;

自旋锁函数

spinlock_tmy_lock=SPIN_LOCK_UNLOCKED;

voidspin_lock_init(spinlock_t*lock);

  voidspin_lock(spinlock_t*lock);

  voidspin_unlock(spinlock_t*lock);

voidspin_lock(spinlock_t*lock);

  voidspin_lock_irqsave(spinlock_t*lock,unsignedlongflags);

  voidspin_lock_irq(spinlock_t*lock);

  voidspin_lock_bh(spinlock_t*lock)

voidspin_unlock(spinlock_t*lock);

  voidspin_unlock_irqrestore(spinlock_t*lock,unsignedlongflags);

  voidspin_unlock_irq(spinlock_t*lock);

  voidspin_unlock_bh(spinlock_t*lock);

  intspin_trylock(spinlock_t*lock);

  intspin_trylock_bh(spinlock_t*lock);

  rwlock_tmy_rwlock=RW_LOCK_UNLOCKED;/*Staticway*/

  rwlock_tmy_rwlock;

  rwlock_init(&my_rwlock);/*Dynamicway*/

 

3)信号量、互斥体机制。

描述信号量的结构体

structsemaphore{

unsignedintcount;

structlist_headwait_list;

};

结构体记录当前的进程信息

structsemaphore_waiter{

structlist_headlist;

structtask_struct*task;

};

实现信号量的申请函数

voiddown(structsemaphore*sem)

{

structsemaphore_waiterwaiter;

if(sem->count>0){

sem->count--;  /*1*/

return;

}

waiter.task=current;/*2*/

list_add_tail(&waiter.list,&sem->wait_list);/*2*/

schedule();/*3*/

}

两个类似的结构体分别描述mutex

structmutex_waiter{

structlist_headlist;

structtask_struct*task;

};

structmutex{

longowner;

structlist_headwait_list;

};

申请互斥量的函数

voidmutex_take(structmutex*mutex)

{

structmutex_waiterwaiter;

if(!

mutex->owner){

mutex->owner=(long)current;/*1*/

return;

}

waiter.task=current;

list_add_tail(&waiter.list,&mutex->wait_list);/*2*/

schedule();/*2*/

}

互斥量的释放代码

intmutex_release(structmutex*mutex)

{

structmutex_waiterwaiter;

if(mutex->owner!

=(long)current)/*1*/

return-1;

if(list_empty(&mutex->wait_list)){

mutex->owner=0;/*2*/

return0;

}

waiter=list_first_entry(&mutex->wait_list,structmutex_waiter,list);

list_del(&waiter->list);

mutex->owner=(long)waiter->task;/*3*/

wake_up_process(waiter->task);/*4*/

return0;

}

 

六、实验体会

(需要填写)

 

指导教师评语:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 初中作文

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

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