在计算机世界,百万分之一的事情会在几秒钟发生,并且问题的结果是严重的!
1、并发的管理
SMP(SymmetricalMulti-Processing)对称多处理机。
竞争情况来自对共享资源的存取。
存取管理的常用技术是加锁或者互斥。
2、旗标的互斥体
当一个进程到了无法做进一步处理的时候,它就去睡眠(阻塞),让出处理器给别人知道以后某个时间它能够再做其他事情。
旗标是一个单个整型值,结合一对函数,成为P和V,一个想要进入临界区的进程将在旗标上调用P,如果旗标的值大于0,这个值递减1并且进程继续,相反,如果旗标的值是0,进程必须等待直到别的进程释放旗标,解锁一个旗标通过调用V完成,这个函数递增旗标的值,如果需要,唤醒等待的进程。
旗标的使用需要包含<asm/semaphore.h>,相关类型是structsemaphore,直接创建一个旗标,使用sema_init来设定它:
Voidsema_init(structsemaphore*sem,intval);
这里val是安排给旗标的初始值。
互斥锁模式的旗标:
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);
这里name是一个旗标变量,前面是初始化为1,后面是初始化为0。
互斥锁在运行时初始化使用下面中的一个:
Voidinit_MUTEX(structsemaphore*sem);
Voidinit_MUTEX_LOCKED(structsemaphore*sem);
3、completions(实现)机制
completion是任务使用的一个轻量级机
制:允许一个线程告诉另一个线程工作已经完成。
completion机制的典型使用是在模块退出时与内核线程的终止一起,当模块准备好被清理时,exit函数告
知线程退出并且等待结束.为此目的,内核包含一个特殊的函数给线程使用:
voidcomplete_and_exit(structcompletion*c,longretval);
4、自旋锁
一个自旋锁是一个互斥设备,只能有2个值:"上锁"和"解锁".它常常实现为一个整数值中的一个单个位.想获取一个特殊锁的代码则测试相关的位.如果锁是可用的,这个"上锁"位被置位并且代码继续进入临界区.相反,如果这个锁已经被别人获得,代码进入一个紧凑的循环中反复检查这个锁,直到它变为可用.这个循环就是自旋锁的"自旋"部分。
5、快速参考
本章已介绍了很多符号给并发的管理.最重要的这些在此总结:
#include<asm/semaphore.h>
定义旗标和其上操作的包含文件.
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);
2个宏定义,用来声明和初始化一个在互斥模式下使用的旗标.
voidinit_MUTEX(structsemaphore*sem);
voidinit_MUTEX_LOCKED(structsemaphore*sem);
这2函数用来在运行时初始化一个旗标.
voiddown(structsemaphore*sem);
intdown_interruptible(structsemaphore*sem);
intdown_trylock(structsemaphore*sem);
voidup(structsemaphore*sem);
加锁和解锁旗标.down使调用进程进入不可打断睡眠,如果需要;down_interruptible,相反,可以被信号打断.down_trylock不睡眠;相反,它立刻返回如果旗标不可用.加锁旗标的代码必须最终使用up解锁它.
structrw_semaphore;
init_rwsem(structrw_semaphore*sem);
旗标的读者/写者版本和初始化它的函数.
voiddown_read(structrw_semaphore*sem);
intdown_read_trylock(structrw_semaphore*sem);
voidup_read(structrw_semaphore*sem);
获得和释放对读者/写者旗标的读存取的函数.
voiddown_write(structrw_semaphore*sem);
intdown_write_trylock(structrw_semaphore*sem);
voidup_write(structrw_semaphore*sem);
voiddowngrade_write(structrw_semaphore*sem);
管理对读者/写者旗标写存取的函数.
#include<linux/completion.h>
DECLARE_COMPLETION(name);
init_completion(structcompletion*c);
INIT_COMPLETION(structcompletionc);
描述Linuxcompletion机制的包含文件,已经初始化completion的正常方法.
INIT_COMPLETION应当只用来重新初始化一个之前已经使用过的completion.
voidwait_for_completion(structcompletion*c);
等待一个completion事件发出.
voidcomplete(structcompletion*c);
voidcomplete_all(structcompletion*c);
发出一个completion事件.completion唤醒,最多,一个等待着的线程,而complete_all唤醒全
部等待者.
voidcomplete_and_exit(structcompletion*c,longretval);
通过调用complete来发出一个completion事件,并且为当前线程调用exit.
#include<linux/spinlock.h>
spinlock_tlock=SPIN_LOCK_UNLOCKED;
spin_lock_init(spinlock_t*lock);
定义自旋锁接口的包含文件,以及初始化锁的2个方法.
voidspin_lock(spinlock_t*lock);
voidspin_lock_irqsave(spinlock_t*lock,unsignedlongflags);
voidspin_lock_irq(spinlock_t*lock);
voidspin_lock_bh(spinlock_t*lock);
加锁一个自旋锁的各种方法,并且,可能地,禁止中断.
intspin_trylock(spinlock_t*lock);
intspin_trylock_bh(spinlock_t*lock);
上面函数的非自旋版本;在获取锁失败时返回0,否则非零.
voidspin_unlock(spinlock_t*lock);
voidspin_unlock_irqrestore(spinlock_t*lock,unsignedlongflags);
voidspin_unlock_irq(spinlock_t*lock);
voidspin_unlock_bh(spinlock_t*lock);
释放一个自旋锁的相应方法.
rwlock_tlock=RW_LOCK_UNLOCKED
rwlock_init(rwlock_t*lock);
初始化读者/写者锁的2个方法.
voidread_lock(rwlock_t*lock);
voidread_lock_irqsave(rwlock_t*lock,unsignedlongflags);
voidread_lock_irq(rwlock_t*lock);
voidread_lock_bh(rwlock_t*lock);
获得一个读者/写者锁的读存取的函数.
voidread_unlock(rwlock_t*lock);
voidread_unlock_irqrestore(rwlock_t*lock,unsignedlongflags);
voidread_unlock_irq(rwlock_t*lock);
voidread_unlock_bh(rwlock_t*lock);
释放一个读者/写者自旋锁的读存取.
voidwrite_lock(rwlock_t*lock);
voidwrite_lock_irqsave(rwlock_t*lock,unsignedlongflags);
voidwrite_lock_irq(rwlock_t*lock);
voidwrite_lock_bh(rwlock_t*lock);
获得一个读者/写者锁的写存取的函数.
voidwrite_unlock(rwlock_t*lock);
voidwrite_unlock_irqrestore(rwlock_t*lock,unsignedlongflags);
voidwrite_unlock_irq(rwlock_t*lock);
voidwrite_unlock_bh(rwlock_t*lock);
释放一个读者/写者自旋锁的写存取的函数.
#include<asm/atomic.h>
atomic_tv=ATOMIC_INIT(value);
voidatomic_set(atomic_t*v,inti);
intatomic_read(atomic_t*v);
voidatomic_add(inti,atomic_t*v);
voidatomic_sub(inti,atomic_t*v);
voidatomic_inc(atomic_t*v);
voidatomic_dec(atomic_t*v);
intatomic_inc_and_test(atomic_t*v);
intatomic_dec_and_test(atomic_t*v);
intatomic_sub_and_test(inti,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);
原子地存取整数变量.atomic_t变量必须只通过这些函数存取.
#include<asm/bitops.h>
voidset_bit(nr,void*addr);
voidclear_bit(nr,void*addr);
voidchange_bit(nr,void*addr);
test_bit(nr,void*addr);
inttest_and_set_bit(nr,void*addr);
inttest_and_clear_bit(nr,void*addr);
inttest_and_change_bit(nr,void*addr);
原子地存取位值;它们可用做标志或者锁变量.使用这些函数阻止任何与并发存取这个位相关的竞争情况.
#include<linux/seqlock.h>
seqlock_tlock=SEQLOCK_UNLOCKED;
seqlock_init(seqlock_t*lock);
定义seqlock的包含文件,已经初始化它们的2个方法.
unsignedintread_seqbegin(seqlock_t*lock);
unsignedintread_seqbegin_irqsave(seqlock_t*lock,unsignedlongflags);
intread_seqretry(seqlock_t*lock,unsignedintseq);
intread_seqretry_irqrestore(seqlock_t*lock,unsignedintseq,unsignedlongflags);
获得一个seqlock-保护的资源的读权限的函数.
voidwrite_seqlock(seqlock_t*lock);
voidwrite_seqlock_irqsave(seqlock_t*lock,unsignedlongflags);
voidwrite_seqlock_irq(seqlock_t*lock);
voidwrite_seqlock_bh(seqlock_t*lock);
获取一个seqlock-保护的资源的写权限的函数.
voidwrite_sequnlock(seqlock_t*lock);
voidwrite_sequnlock_irqrestore(seqlock_t*lock,unsignedlongflags);
voidwrite_sequnlock_irq(seqlock_t*lock);
voidwrite_sequnlock_bh(seqlock_t*lock);
释放一个seqlock-保护的资源的写权限的函数.
#include<linux/rcupdate.h>
需要使用读取-拷贝-更新(RCU)机制的包含文件.
voidrcu_read_lock;
voidrcu_read_unlock;
获取对由RCU保护的资源的原子读权限的宏定义.
voidcall_rcu(structrcu_head*head,void(*func)(void*arg),void*arg);
安排一个回调在所有处理器已经被调度以及一个RCU-保护的资源可用被安全的释放之后运行.
相关推荐
LDD3学习笔记设备模型之底层实现(kobject,kset)[汇编].pdf
ldd code ldd3驱动源代码 ldd code ldd3驱动源代码
ldd3中文版、chmldd3中文版chm
本资源为ldd3详解,该书中详细介绍了ldd3的使用以及各种驱动的设置
LDD-LinuxDeviceDrivers#1书籍-一些书中的原始码和范例目录书籍#2 study--本人的linux学习以及驱动代码目录书籍学习Linux内核的设计与实现,包括文档和示例代码,文档与同步更新自己实现的一些linux内核的驱动代码...
LDD3配套源码,配合我的百度云分享的虚拟机可以直接编译运行(虚拟机另行在我上传的资源里下载,相关可以参考我的LDD3系列博客)
ldd3 中文
LDD2+LDD3 linux设备驱动
Linux 设备驱动 Edition 3 - LDD3中文版,学习linux必备之书,pdf格式
ldd3-examples-3.x, 在 linux 3.x 之后,端口LDD3源代码示例 ldd3-examples-3.xlinux 3 。x 之后LDD3源代码示例的端口背景LDD3是Linux设备驱动程序,第三版。 这是一本关于如何编写linux设备驱动程序的。 你可以从 ...
经典 LDD3,linux驱动开发 linux驱动开发
由于对Linux设备驱动程序设计的需求,所以前段时间在网上下载了LDD3的HTML格式文档,在看的时候感觉不太好看,同时为了打印方便,把它转化为PDF格式,所以在此与大家一起分享。 由于本资料不是本人自创,也是来自于...
这是ldd3的英文原版书以及相应例程的源码,希望对正在学习linux驱动的朋友们有所帮助
LDD3是linux驱动开发的基础入门级图书,适合刚接触linux驱动的新手学习。
LDD6410 S3C6410开发板原理图
主要是对LDD3中的实例进行测试,修改,调试。
linux LDD 3 LINUX设备驱动程序源码。。
linux device driver\ldd3英文版附源码.rar
ldd3 example ldd3 example