Linux系统处于一个高并发的运行环境,不管是系统调用还是中断都要求可重入,但是有一些系统资源处于临界区,因此,必须保证临界区资源访问的原子性。

对于临界区资源被占用时,发起访问的进程,有三种处理方法——睡眠、阻塞以及撤销。

Linux驱动编程中,通常不建议使用锁机制,因为容易导致死锁问题。不使用锁的场景,尽量使用kfifo缓冲队列来存取数据;在必须使用锁的场景,建议使用信号量和自旋锁。

信号量通常用在可以睡眠的场景,如进程上下文;而自旋锁通常用在不可睡眠的场景,如中断上下文。

1、信号量

#include <linux/semaphore.h>

信号量初始化
void sema_init(struct semaphore *sem, int val); 互斥信号量
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name); void init_MUTEX(struct semaphore *sem);
void init_MUTEX_LOCKED(struct semaphore *sem); 获取信号量
void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem); /* 可中断,即进入睡眠状态等待信号量,需要一直检查返回值并且针对性地响应 */
int down_trylock(struct semaphore *sem); /* 从不睡眠,如果信号量被占用,立刻返回 */ 释放信号量
void up(struct semaphore *sem);

示例:

if (down_interruptible(&sem))
return -ERESTARTSYS; /* 临界区资源访问 */ up(&sem);

1.1、读写信号量

由信号量衍生,可以允许多个用户并发读,一个用户互斥写。

#include <linux/rwsem.h>

/* 初始化 */
void init_rwsem(struct rw_semaphore *sem); /* 读者接口 */
void down_read(struct rw_semaphore *sem);
void down_read_trylock(struct rw_semaphore *sem);
void up_read(struct rw_semaphore *sem); /* 写者接口 */
void down_write(struct rw_semaphore *sem);
void down_write_trylock(struct rw_semaphore *sem);
void up_write(struct rw_semaphore *sem);

2、自旋锁

#include <linux/spinlock.h>

初始化
spinlock_t my_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_irqsave(spinlock_t *lock, unsigned long flags);
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); 获取自旋锁时禁止中断,释放时打开中断
void spin_lock_irq(spinlock_t *lock);
void spin_unlock_irq(spinlock_t *lock);

2.1、读写自旋锁

类似于读写信号量,读写自旋锁是自旋锁的衍生。

3、原子量(atomic)

4、顺序锁(seqlock)

顺序锁用来保护较小的资源,快速存取的场景。它允许读者释放对资源的存取,但是要求读者检查与写者的冲突,如果发生冲突,重试存取操作。

seqlock通常不能用在保护包含指针的数据结构,因为读者可能跟随一个无效指针而写者在改变数据结构。

#include <linux/seqlock.h>

seqlock_init(seqlock_t *lock);

5、读取-拷贝-更新(RCU)

一种高级的互斥方法

Linux驱动开发4——并发和竞态的更多相关文章

  1. Linux内核中的并发与竞态概述

    1.前言 众所周知,Linux系统是一个多任务的操作系统,当多个任务同时访问同一片内存区域的时候,这些任务可能会相互覆盖内存中数据,从而造成内存中的数据混乱,问题严重的话,还可能会导致系统崩溃. 2. ...

  2. linux设备驱动程序之并发和竞态(二)

    事实上这blog都是阅读ldd3时的一些总结,巩固自己的学习.也方便后期的使用.大家也能够直接阅读ldd3原文. 锁陷阱         所谓的锁陷阱就是防止死锁.         不明白的规则:   ...

  3. 漫画|Linux 并发、竞态、互斥锁、自旋锁、信号量都是什么鬼?(转)

    知乎链接:https://zhuanlan.zhihu.com/p/57354304 1. 锁的由来? 学习linux的时候,肯定会遇到各种和锁相关的知识,有时候自己学好了一点,感觉半桶水的自己已经可 ...

  4. linux设备驱动第五篇:驱动中的并发与竟态

    综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被 ...

  5. 《Linux 设备驱动程序》读后感。 并发,竞态,死锁。

    1. 概念 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行. 来源: 1. Linux ...

  6. Linux内核分析(七)----并发与竞态

    原文:Linux内核分析(七)----并发与竞态 Linux内核分析(七) 这两天家里的事好多,我们今天继续接着上一次的内容学习,上次我们完善了字符设备控制方法,并深入分析了系统调用的实质,今天我们主 ...

  7. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  8. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入L ...

  9. LDD3之并发和竞态-completion(完毕量)的学习和验证

    LDD3之并发和竞态-completion(完毕量)的学习和验证 首先说下測试环境: Linux2.6.32.2 Mini2440开发板 一開始难以理解书上的书面语言,这里<linux中同步样例 ...

随机推荐

  1. SSM框架中数据库无法连接的问题

    首先是SSM框架中所有的配置都是没有问题的,而且项目在其他人的环境上也能正常访问数据库:那么最有可能的就是数据库版本的问题导致数据库连接不上,服务器给我的报错是: 15:37:25.902 [C3P0 ...

  2. python是强语言还是弱语言?

    python是强语言还是弱语言,没有一个具体官方的说法 数据类型也就是变量类型,一般编程语言的变量类型可以分成下面两类. 静态类型与动态类型 静态类型语言:一种在编译期间就确定数据类型的语言.大多数静 ...

  3. TMS320F28335——下载程序到flash中

    一.让CCS软件支持Flash烧写 添加F28335.cmd文件 如图屏蔽掉25335_RAM_lnk.cmd 2.支持从Flash中拷贝文件到RAM中 添加DSP2832x_MemCopy.c 在主 ...

  4. 方法签名_spring aop_around

    //注解签名 方法签名 Signature signature = pjp.getSignature(); MethodSignature methodSignature= (MethodSignat ...

  5. 移动端布局的思考和rem的设置

    如下方法如有不正确的地方,欢迎指正 前提: 设置稿750px 目标:40px = 1rem js设置方法:(小于等于750屏幕等比缩放) ;(function (doc, win, undefined ...

  6. Nginx中配置https中引用http的问题

    Nginx中配置https中引用http的问题 遇到问题: 今天公司要在后台增加直播入口,使用腾讯云的实时音视频,要求是必须使用https,在配置完强制跳转https候,发现后台无法上传图片,在浏览器 ...

  7. Spring基础15——通过工厂方法来配置bean

    1.什么是工厂方法 这里的工厂方法指的是创建指定bean的方法.工厂方法又分为静态工厂方法和实例工厂方法. 2.静态工厂方法配置bean 调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中 ...

  8. Codeforces Round #427 (Div. 2) - D

    题目链接:http://codeforces.com/contest/835/problem/D 题意:给定一个字符串,定义kth回文是左半部分等于右半部分,并且左半部分和右半部分都是(k-1)th回 ...

  9. Codeforces 931 概率DP

    A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...

  10. pandas 的axis参数的理解

    # pandas的axis参数怎样理解? # axis=0 或者 "index": # 如果是单行操作,就指的是某一行 # 如果是聚合操作,指的是跨行cross rows # ax ...