解决竞态(race conditions)最根本的途径是对共享资源的互斥访问,访问共享资源的代码区被称为临界区(critical sections),对临界区的代码需要以某种互斥机制加以保护。
常见的互斥机制有:中断屏蔽、原子操作、自旋锁、信号量、互斥体。

1. 中断屏蔽
由于linux内核的进程调度和异步IO等操作都是依赖中断来实现的,所以中断屏蔽也可以避免内核强占进程之间的竞态发生。
定义在linux/irqflags.h,实现在asm/irqflags.h中。
local_irq_disable();
local_irq_enable();

local_irq_save(flags);
local_irq_restore(flags);

local_bh_disable();
local_bh_enable();

2. 原子操作
原子操作分类:整型原子操作和位原子操作
整型原子操作
asm/atomic.h
void atomic_set(atomic_t *v, int i);
atomic_t v = ATOMIC_INIT(0);
atomic_read(atomic_t *v);
void atomic_add(int i, atomic_t *v);
void atomic_sub(int i, atomic_t *v);
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(atomic_t *v);
操作后测试是否为0,为0返回true,否则返回false。
int atomic_add_return(int i, atomic_t *v);
操作后返回新值。

位原子操作
asm/bitops.h
void set_bit(nr, void *addr);
void clear_bit(nr, void *addr);
void change_bie(nr, void *addr);
test_bit(nr, void *addr);
int test_and_set_bit(nr, void *addr);
int test_and_clear_bit(nr, void *addr);
int test_and_change_bit(nr, void *addr);

3. 自旋锁
1)自旋锁主要针对SMP或单CPU且内核可强占的情况,对于单CPU且内核不可强占的系统自旋锁退化为空操作。
2)在单CPU且内核可强占的系统中,自旋锁持有期间内核的强占被禁止。

使用注意:
1)不能递归持有自旋锁。
2)持有自旋锁后不能阻塞。

linux/spinlock_types.h
spinlock_t lock;
spin_lock_init(&lock);
spin_lock(&lock);
spin_trylock(&lock);
spin_unlock(&lock);

spin_lock_irq();
spin_unlock_irq();
spin_lock_irqsave();
spin_unlock_irqrestore();
spin_lock_bh();
spin_unlock_bh();

读写自旋锁
写操作时最多只能有一个写进程。
顺序锁

4. 信号量
linux/semaphore.h,实现在ipc/sem.c和kernel/semaphore.c中。
struct semaphore sem;
void sema_init(struct semaphore *sem, int val);
void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);
void up(struct semaphore *sem);

5. 互斥体
linux/mutex.h       kernel/mutex.c
struct mutex mymutex;
mutex_init(&mymutex);
void fastcall mutex_lock(struct mutex *lock);
int fastcall mutex_lock_interruptible(struct mutex *lock);
int fastcall mutex_trylock(struct mutex *lock);
void fastcall mutex_unlock(struct mutex *lock);

总结
1、信号量是进程级的,用于多个进程之间对资源的互斥。如果竞争失败,会发生进程上下文切换,当前进程进入休眠状态。
2、自旋锁得不到锁时会在原地自旋一直到获取锁,它节省了上下文的切换时间,所以一般用于要保护的临界区访问时间比较短的时候,否则会降低系统效率。

自旋锁和信号量选用原则
1、临界区执行时间比较小时,采用自旋锁,否则使用信号量。
2、信号量所包含的临界区包含可能引起阻塞的代码,而自旋锁要绝对避免在临界区使用阻塞代码。
3、信号量运用进程上下文,若要运于中断中,应用down_trylock()方式进行,不能获取就立即返回,避免阻塞。

参考:

1. linux设备驱动开发详解 宋宝华

2. linux并发控制

linux并发concurrency控制的更多相关文章

  1. Linux Shell多进程并发以及并发数控制

    1. 基础知识准备 1.1. linux后台进程 Unix是一个多任务系统,允许多用户同时运行多个程序.shell的元字符&提供了在后台运行不需要键盘输入的程序的方法.输入命令后,其后紧跟&a ...

  2. MySQL--InnoDB并发线程控制

    InnoDB并发线程控制 MySQL InnoDB存储引擎提供innodb_thread_concurrency来控制进入InnoDB 存储引擎的线程数,以限制InnoDB存储引擎层的并发量. 当in ...

  3. linux并发服务器设计

    linux 并发服务器: http://blog.csdn.net/ygl840455828ygl/article/details/52438167 http://www.2cto.com/os/20 ...

  4. Redis并发锁控制

    为了防止用户在页面上重复点击或者同时发起多次请求,请求处理需要操作redis缓存,这个时候需要对并发边界进行并发锁控制,实现思路: 由于每个页面发起的请求带的token具备唯一性,可以将token作为 ...

  5. Server Develop (五) Linux并发模型

    Linux并发模型 目前可以实现并发程序的方法有Apache模型(Process Per Connection,简称PPC),TPC(Thread PerConnection)模型,以及select模 ...

  6. Linux iptables 应用控制访问SSH服务

    Title:Linux iptables 应用控制访问SSH服务  --2012-02-23 17:51 今天用到了以前从来没有用到过的,iptables控制访问,只允许外部访问SSH服务(22号端口 ...

  7. 并发(Concurrency)和并行(Parallelism)的区别

    最近在读<real world haskell>里关于并行的一章时,看到作者首先对并发(Concurrency)和并行(Parallelism)的区别进行了定义和解释.以前我对这个问题也是 ...

  8. Linux并发模型

    Linux并发模型 Linux并发模型 目前可以实现并发程序的方法有Apache模型(Process Per Connection,简称PPC),TPC(Thread PerConnection)模型 ...

  9. 并行(Parallelism)与并发(Concurrency)

    并行(Parallelism):多任务在同一时刻运行.例如,多个任务在多核处理器上运行. 并发(Concurrency):两个或者两个以上的任务在一段时间内开始.运行.完成,这意味着它们不是在同一时刻 ...

随机推荐

  1. 如何用python的装饰器定义一个像C++一样的强类型函数

        Python作为一个动态的脚本语言,其函数在定义时是不需要指出参数的类型,也不需要指出函数是否有返回值.本文将介绍如何使用python的装饰器来定义一个像C++那样的强类型函数.接下去,先介绍 ...

  2. Windows下面安装和配置Solr 4.9(二)

    将Solr和Tomcat结合: 1.在D盘下创建目录 D:\Demos\Solr 2.解压solr-4.9.0文件,我这里下载的是这个4.9版本,将example文件夹下的solr文件夹中的所有文件( ...

  3. python学习笔记013——模块

    1 模块module 1.1 模块是什么 模块是包含一系列的变量,函数,类等程序组 模块通常是一个文件,以.py结尾 1.2 模块的作用 1. 让一些相关的函数,变量,类等有逻辑的组织在一起,使逻辑更 ...

  4. LINUX使用DVD光盘或者ISO作为本地YUM源

    先把光盘或 ISO 文件挂载到文件系统: # mkdir /media/iso 挂载光盘: # mount /dev/cdrom /media/iso 或挂载 ISO 文件: mount -o loo ...

  5. SYS_R12 MOAC多组织的四个应用(案例)

    2014-05-31 Created By BaoXinjian

  6. 关于c语言内存分配,malloc,free,和段错误,内存泄露

    1.   C语言的函数malloc和free (1) 函数malloc和free在头文件<stdlib.h>中的原型及参数        void * malloc(size_t size ...

  7. Web - TCP与UDP的差别

    是否面向连接:TCP面向连接.UDP面向非连接. 传输可靠性:TCP可靠.UDP不可靠. 应用场合:TCP经常使用于传输大量数据,UDP经常使用于传输少量数据. 速度:TCP传输速度较慢,而UDP速度 ...

  8. 如何理解Latency和Throughput: 吞吐量和延迟

    Latency,中文译作延迟.Throughput,中文译作吞吐量.它们是衡量软件系统的最常见的两个指标. 延迟一般包括单向延迟(One-way Latency)和往返延迟(Round Trip La ...

  9. Es6 函数式编程 MayBe函子的简单示例

    初级函子的作用非常简单,使用场景主要体现在:深入访问object的属性的时候,不会担心由于属性不存在.undefined.null等问题出现异常. MayBe.js var MayBe = funct ...

  10. java 随机日期

    java 在某个范围日期内获取一个日期,再以这个日期作为开始日期,获取到随机n天后的日期 /** * 在beginDate和endDate之间获取一个随机日期作为开始日期 * @param begin ...